diff options
Diffstat (limited to 'src/test/ui/try-block')
26 files changed, 753 insertions, 0 deletions
diff --git a/src/test/ui/try-block/issue-45124.rs b/src/test/ui/try-block/issue-45124.rs new file mode 100644 index 000000000..942014c91 --- /dev/null +++ b/src/test/ui/try-block/issue-45124.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unreachable_code)] +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + let mut a = 0; + let () = { + let _: Result<(), ()> = try { + let _ = Err(())?; + return + }; + a += 1; + }; + a += 2; + assert_eq!(a, 3); +} diff --git a/src/test/ui/try-block/try-block-bad-lifetime.rs b/src/test/ui/try-block/try-block-bad-lifetime.rs new file mode 100644 index 000000000..d9524e99f --- /dev/null +++ b/src/test/ui/try-block/try-block-bad-lifetime.rs @@ -0,0 +1,37 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +#[inline(never)] +fn do_something_with<T>(_x: T) {} + +// This test checks that borrows made and returned inside try blocks are properly constrained +pub fn main() { + { + // Test that borrows returned from a try block must be valid for the lifetime of the + // result variable + let result: Result<(), &str> = try { + let my_string = String::from(""); + let my_str: & str = & my_string; + //~^ ERROR `my_string` does not live long enough + Err(my_str) ?; + Err("") ?; + }; + do_something_with(result); + } + + { + // Test that borrows returned from try blocks freeze their referent + let mut i = 5; + let k = &mut i; + let mut j: Result<(), &mut i32> = try { + Err(k) ?; + i = 10; //~ ERROR cannot assign to `i` because it is borrowed + }; + ::std::mem::drop(k); //~ ERROR use of moved value: `k` + i = 40; //~ ERROR cannot assign to `i` because it is borrowed + + let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; + *i_ptr = 50; + } +} diff --git a/src/test/ui/try-block/try-block-bad-lifetime.stderr b/src/test/ui/try-block/try-block-bad-lifetime.stderr new file mode 100644 index 000000000..ea079e30d --- /dev/null +++ b/src/test/ui/try-block/try-block-bad-lifetime.stderr @@ -0,0 +1,52 @@ +error[E0597]: `my_string` does not live long enough + --> $DIR/try-block-bad-lifetime.rs:15:33 + | +LL | let result: Result<(), &str> = try { + | ------ borrow later stored here +LL | let my_string = String::from(""); +LL | let my_str: & str = & my_string; + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | }; + | - `my_string` dropped here while still borrowed + +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-bad-lifetime.rs:29:13 + | +LL | let k = &mut i; + | ------ borrow of `i` occurs here +... +LL | i = 10; + | ^^^^^^ assignment to borrowed `i` occurs here +LL | }; +LL | ::std::mem::drop(k); + | - borrow later used here + +error[E0382]: use of moved value: `k` + --> $DIR/try-block-bad-lifetime.rs:31:26 + | +LL | let k = &mut i; + | - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait +LL | let mut j: Result<(), &mut i32> = try { +LL | Err(k) ?; + | - value moved here +... +LL | ::std::mem::drop(k); + | ^ value used here after move + +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-bad-lifetime.rs:32:9 + | +LL | let k = &mut i; + | ------ borrow of `i` occurs here +... +LL | i = 40; + | ^^^^^^ assignment to borrowed `i` occurs here +LL | +LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; + | - borrow later used here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0382, E0506, E0597. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/try-block/try-block-bad-type.rs b/src/test/ui/try-block/try-block-bad-type.rs new file mode 100644 index 000000000..30ae96763 --- /dev/null +++ b/src/test/ui/try-block/try-block-bad-type.rs @@ -0,0 +1,21 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +pub fn main() { + let res: Result<u32, std::array::TryFromSliceError> = try { + Err("")?; //~ ERROR `?` couldn't convert the error + 5 + }; + + let res: Result<i32, i32> = try { + "" //~ ERROR type mismatch + }; + + let res: Result<i32, i32> = try { }; //~ ERROR type mismatch + + let res: () = try { }; + //~^ ERROR a `try` block must return `Result` or `Option` + + let res: i32 = try { 5 }; //~ ERROR a `try` block must return `Result` or `Option` +} diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr new file mode 100644 index 000000000..f9906713f --- /dev/null +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -0,0 +1,42 @@ +error[E0277]: `?` couldn't convert the error to `TryFromSliceError` + --> $DIR/try-block-bad-type.rs:7:16 + | +LL | Err("")?; + | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the trait `From<Infallible>` is implemented for `TryFromSliceError` + = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>` + +error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str` + --> $DIR/try-block-bad-type.rs:12:9 + | +LL | "" + | ^^ expected `i32`, found `&str` + +error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == ()` + --> $DIR/try-block-bad-type.rs:15:39 + | +LL | let res: Result<i32, i32> = try { }; + | ^ expected `i32`, found `()` + +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) + --> $DIR/try-block-bad-type.rs:17:25 + | +LL | let res: () = try { }; + | ^ could not wrap the final value of the block as `()` doesn't implement `Try` + | + = help: the trait `Try` is not implemented for `()` + +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) + --> $DIR/try-block-bad-type.rs:20:26 + | +LL | let res: i32 = try { 5 }; + | ^ could not wrap the final value of the block as `i32` doesn't implement `Try` + | + = help: the trait `Try` is not implemented for `i32` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/try-block/try-block-catch.rs b/src/test/ui/try-block/try-block-catch.rs new file mode 100644 index 000000000..d16501561 --- /dev/null +++ b/src/test/ui/try-block/try-block-catch.rs @@ -0,0 +1,10 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + let res: Option<bool> = try { + true + } catch { }; + //~^ ERROR keyword `catch` cannot follow a `try` block +} diff --git a/src/test/ui/try-block/try-block-catch.stderr b/src/test/ui/try-block/try-block-catch.stderr new file mode 100644 index 000000000..39cf943f4 --- /dev/null +++ b/src/test/ui/try-block/try-block-catch.stderr @@ -0,0 +1,10 @@ +error: keyword `catch` cannot follow a `try` block + --> $DIR/try-block-catch.rs:8:7 + | +LL | } catch { }; + | ^^^^^ + | + = help: try using `match` on the result of the `try` block instead + +error: aborting due to previous error + diff --git a/src/test/ui/try-block/try-block-in-edition2015.rs b/src/test/ui/try-block/try-block-in-edition2015.rs new file mode 100644 index 000000000..009642973 --- /dev/null +++ b/src/test/ui/try-block/try-block-in-edition2015.rs @@ -0,0 +1,10 @@ +// compile-flags: --edition 2015 + +pub fn main() { + let try_result: Option<_> = try { + //~^ ERROR expected struct, variant or union type, found macro `try` + let x = 5; //~ ERROR expected identifier, found keyword + x + }; + assert_eq!(try_result, Some(5)); +} diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr new file mode 100644 index 000000000..a00064c44 --- /dev/null +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -0,0 +1,24 @@ +error: expected identifier, found keyword `let` + --> $DIR/try-block-in-edition2015.rs:6:9 + | +LL | let try_result: Option<_> = try { + | --- while parsing this struct +LL | +LL | let x = 5; + | ^^^ expected identifier, found keyword + +error[E0574]: expected struct, variant or union type, found macro `try` + --> $DIR/try-block-in-edition2015.rs:4:33 + | +LL | let try_result: Option<_> = try { + | ^^^ not a struct, variant or union type + | + = note: if you want the `try` keyword, you need Rust 2018 or later +help: use `!` to invoke the macro + | +LL | let try_result: Option<_> = try! { + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/try-block/try-block-in-match.rs b/src/test/ui/try-block/try-block-in-match.rs new file mode 100644 index 000000000..cd0b967e7 --- /dev/null +++ b/src/test/ui/try-block/try-block-in-match.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + match try { } { + Err(()) => (), + Ok(()) => (), + } +} diff --git a/src/test/ui/try-block/try-block-in-return.rs b/src/test/ui/try-block/try-block-in-return.rs new file mode 100644 index 000000000..a15bfeef1 --- /dev/null +++ b/src/test/ui/try-block/try-block-in-return.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn issue_76271() -> Option<i32> { + return try { 4 } +} + +fn main() { + assert_eq!(issue_76271(), Some(4)); +} diff --git a/src/test/ui/try-block/try-block-in-while.rs b/src/test/ui/try-block/try-block-in-while.rs new file mode 100644 index 000000000..69793df52 --- /dev/null +++ b/src/test/ui/try-block/try-block-in-while.rs @@ -0,0 +1,8 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + while try { false } {} + //~^ ERROR a `try` block must +} diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr new file mode 100644 index 000000000..62cc26dd4 --- /dev/null +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -0,0 +1,11 @@ +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) + --> $DIR/try-block-in-while.rs:6:17 + | +LL | while try { false } {} + | ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try` + | + = help: the trait `Try` is not implemented for `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs b/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs new file mode 100644 index 000000000..cd2ddf63a --- /dev/null +++ b/src/test/ui/try-block/try-block-maybe-bad-lifetime.rs @@ -0,0 +1,44 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +#[inline(never)] +fn do_something_with<T>(_x: T) {} + +// This test checks that borrows made and returned inside try blocks are properly constrained +pub fn main() { + { + // Test that a borrow which *might* be returned still freezes its referent + let mut i = 222; + let x: Result<&i32, ()> = try { + Err(())?; + &i + }; + i = 0; //~ ERROR cannot assign to `i` because it is borrowed + let _ = i; + do_something_with(x); + } + + { + let x = String::new(); + let _y: Result<(), ()> = try { + Err(())?; + ::std::mem::drop(x); + }; + println!("{}", x); //~ ERROR borrow of moved value: `x` + } + + { + // Test that a borrow which *might* be assigned to an outer variable still freezes + // its referent + let mut i = 222; + let mut j = &-1; + let _x: Result<(), ()> = try { + Err(())?; + j = &i; + }; + i = 0; //~ ERROR cannot assign to `i` because it is borrowed + let _ = i; + do_something_with(j); + } +} diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr new file mode 100644 index 000000000..c9f2a3ed9 --- /dev/null +++ b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr @@ -0,0 +1,42 @@ +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-maybe-bad-lifetime.rs:17:9 + | +LL | &i + | -- borrow of `i` occurs here +LL | }; +LL | i = 0; + | ^^^^^ assignment to borrowed `i` occurs here +LL | let _ = i; +LL | do_something_with(x); + | - borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/try-block-maybe-bad-lifetime.rs:28:24 + | +LL | let x = String::new(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +... +LL | ::std::mem::drop(x); + | - value moved here +LL | }; +LL | println!("{}", x); + | ^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-maybe-bad-lifetime.rs:40:9 + | +LL | j = &i; + | -- borrow of `i` occurs here +LL | }; +LL | i = 0; + | ^^^^^ assignment to borrowed `i` occurs here +LL | let _ = i; +LL | do_something_with(j); + | - borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0506. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs new file mode 100644 index 000000000..f4f45abcc --- /dev/null +++ b/src/test/ui/try-block/try-block-opt-init.rs @@ -0,0 +1,16 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn use_val<T: Sized>(_x: T) {} + +pub fn main() { + let cfg_res; + let _: Result<(), ()> = try { + Err(())?; + cfg_res = 5; + Ok::<(), ()>(())?; + use_val(cfg_res); + }; + assert_eq!(cfg_res, 5); //~ ERROR E0381 +} diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr new file mode 100644 index 000000000..c39738501 --- /dev/null +++ b/src/test/ui/try-block/try-block-opt-init.stderr @@ -0,0 +1,17 @@ +error[E0381]: used binding `cfg_res` is possibly-uninitialized + --> $DIR/try-block-opt-init.rs:15:5 + | +LL | let cfg_res; + | ------- binding declared here but left uninitialized +... +LL | cfg_res = 5; + | ----------- binding initialized here in some conditions +... +LL | assert_eq!(cfg_res, 5); + | ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` used here but it is possibly-uninitialized + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/try-block/try-block-type-error.rs b/src/test/ui/try-block/try-block-type-error.rs new file mode 100644 index 000000000..fe1993a37 --- /dev/null +++ b/src/test/ui/try-block/try-block-type-error.rs @@ -0,0 +1,18 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn foo() -> Option<()> { Some(()) } + +fn main() { + let _: Option<f32> = try { + foo()?; + 42 + //~^ ERROR type mismatch + }; + + let _: Option<i32> = try { + foo()?; + }; + //~^ ERROR type mismatch +} diff --git a/src/test/ui/try-block/try-block-type-error.stderr b/src/test/ui/try-block/try-block-type-error.stderr new file mode 100644 index 000000000..3e9a584a5 --- /dev/null +++ b/src/test/ui/try-block/try-block-type-error.stderr @@ -0,0 +1,18 @@ +error[E0271]: type mismatch resolving `<Option<f32> as Try>::Output == {integer}` + --> $DIR/try-block-type-error.rs:10:9 + | +LL | 42 + | ^^ + | | + | expected `f32`, found integer + | help: use a float literal: `42.0` + +error[E0271]: type mismatch resolving `<Option<i32> as Try>::Output == ()` + --> $DIR/try-block-type-error.rs:16:5 + | +LL | }; + | ^ expected `i32`, found `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/try-block/try-block-unreachable-code-lint.rs b/src/test/ui/try-block/try-block-unreachable-code-lint.rs new file mode 100644 index 000000000..e1d82ea36 --- /dev/null +++ b/src/test/ui/try-block/try-block-unreachable-code-lint.rs @@ -0,0 +1,76 @@ +// Test unreachable_code lint for `try {}` block ok-wrapping. See issues #54165, #63324. + +// compile-flags: --edition 2018 +// check-pass +#![feature(try_blocks)] +#![warn(unreachable_code)] + +fn err() -> Result<u32, ()> { + Err(()) +} + +// In the following cases unreachable code is autogenerated and should not be reported. + +fn test_ok_wrapped_divergent_expr_1() { + let res: Result<u32, ()> = try { + loop { + err()?; + } + }; + println!("res: {:?}", res); +} + +fn test_ok_wrapped_divergent_expr_2() { + let _: Result<u32, ()> = try { + return + }; +} + +fn test_autogenerated_unit_after_divergent_expr() { + let _: Result<(), ()> = try { + return; + }; +} + +// In the following cases unreachable code should be reported. + +fn test_try_block_after_divergent_stmt() { + let _: Result<u32, ()> = { + return; + + try { + loop { + err()?; + } + } + //~^^^^^ WARNING unreachable expression + }; +} + +fn test_wrapped_divergent_expr() { + let _: Result<u32, ()> = { + Err(return) + //~^ WARNING unreachable call + }; +} + +fn test_expr_after_divergent_stmt_in_try_block() { + let res: Result<u32, ()> = try { + loop { + err()?; + } + + 42 + //~^ WARNING unreachable expression + }; + println!("res: {:?}", res); +} + +fn main() { + test_ok_wrapped_divergent_expr_1(); + test_ok_wrapped_divergent_expr_2(); + test_autogenerated_unit_after_divergent_expr(); + test_try_block_after_divergent_stmt(); + test_wrapped_divergent_expr(); + test_expr_after_divergent_stmt_in_try_block(); +} diff --git a/src/test/ui/try-block/try-block-unreachable-code-lint.stderr b/src/test/ui/try-block/try-block-unreachable-code-lint.stderr new file mode 100644 index 000000000..9fc0b661f --- /dev/null +++ b/src/test/ui/try-block/try-block-unreachable-code-lint.stderr @@ -0,0 +1,40 @@ +warning: unreachable expression + --> $DIR/try-block-unreachable-code-lint.rs:41:9 + | +LL | return; + | ------ any code following this expression is unreachable +LL | +LL | / try { +LL | | loop { +LL | | err()?; +LL | | } +LL | | } + | |_________^ unreachable expression + | +note: the lint level is defined here + --> $DIR/try-block-unreachable-code-lint.rs:6:9 + | +LL | #![warn(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: unreachable call + --> $DIR/try-block-unreachable-code-lint.rs:52:9 + | +LL | Err(return) + | ^^^ ------ any code following this expression is unreachable + | | + | unreachable call + +warning: unreachable expression + --> $DIR/try-block-unreachable-code-lint.rs:63:9 + | +LL | / loop { +LL | | err()?; +LL | | } + | |_________- any code following this expression is unreachable +LL | +LL | 42 + | ^^ unreachable expression + +warning: 3 warnings emitted + diff --git a/src/test/ui/try-block/try-block-unused-delims.fixed b/src/test/ui/try-block/try-block-unused-delims.fixed new file mode 100644 index 000000000..756081738 --- /dev/null +++ b/src/test/ui/try-block/try-block-unused-delims.fixed @@ -0,0 +1,29 @@ +// check-pass +// compile-flags: --edition 2018 +// run-rustfix + +#![feature(try_blocks)] +#![warn(unused_parens, unused_braces)] + +fn consume<T>(_: Result<T, T>) -> T { todo!() } + +fn main() { + consume(try {}); + //~^ WARN unnecessary parentheses + + consume(try {}); + //~^ WARN unnecessary braces + + match try {} { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } + + if let Err(()) = try {} {} + //~^ WARN unnecessary parentheses + + match try {} { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } +} diff --git a/src/test/ui/try-block/try-block-unused-delims.rs b/src/test/ui/try-block/try-block-unused-delims.rs new file mode 100644 index 000000000..ce087fb35 --- /dev/null +++ b/src/test/ui/try-block/try-block-unused-delims.rs @@ -0,0 +1,29 @@ +// check-pass +// compile-flags: --edition 2018 +// run-rustfix + +#![feature(try_blocks)] +#![warn(unused_parens, unused_braces)] + +fn consume<T>(_: Result<T, T>) -> T { todo!() } + +fn main() { + consume((try {})); + //~^ WARN unnecessary parentheses + + consume({ try {} }); + //~^ WARN unnecessary braces + + match (try {}) { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } + + if let Err(()) = (try {}) {} + //~^ WARN unnecessary parentheses + + match (try {}) { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } +} diff --git a/src/test/ui/try-block/try-block-unused-delims.stderr b/src/test/ui/try-block/try-block-unused-delims.stderr new file mode 100644 index 000000000..765cd9c0f --- /dev/null +++ b/src/test/ui/try-block/try-block-unused-delims.stderr @@ -0,0 +1,72 @@ +warning: unnecessary parentheses around function argument + --> $DIR/try-block-unused-delims.rs:11:13 + | +LL | consume((try {})); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/try-block-unused-delims.rs:6:9 + | +LL | #![warn(unused_parens, unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - consume((try {})); +LL + consume(try {}); + | + +warning: unnecessary braces around function argument + --> $DIR/try-block-unused-delims.rs:14:13 + | +LL | consume({ try {} }); + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/try-block-unused-delims.rs:6:24 + | +LL | #![warn(unused_parens, unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ try {} }); +LL + consume(try {}); + | + +warning: unnecessary parentheses around `match` scrutinee expression + --> $DIR/try-block-unused-delims.rs:17:11 + | +LL | match (try {}) { + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | + +warning: unnecessary parentheses around `let` scrutinee expression + --> $DIR/try-block-unused-delims.rs:22:22 + | +LL | if let Err(()) = (try {}) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let Err(()) = (try {}) {} +LL + if let Err(()) = try {} {} + | + +warning: unnecessary parentheses around `match` scrutinee expression + --> $DIR/try-block-unused-delims.rs:25:11 + | +LL | match (try {}) { + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | + +warning: 5 warnings emitted + diff --git a/src/test/ui/try-block/try-block.rs b/src/test/ui/try-block/try-block.rs new file mode 100644 index 000000000..c29ccc704 --- /dev/null +++ b/src/test/ui/try-block/try-block.rs @@ -0,0 +1,75 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +struct catch {} + +pub fn main() { + let catch_result: Option<_> = try { + let x = 5; + x + }; + assert_eq!(catch_result, Some(5)); + + let mut catch = true; + while catch { catch = false; } + assert_eq!(catch, false); + + catch = if catch { false } else { true }; + assert_eq!(catch, true); + + match catch { + _ => {} + }; + + let catch_err: Result<_, i32> = try { + Err(22)?; + 1 + }; + assert_eq!(catch_err, Err(22)); + + let catch_okay: Result<i32, i32> = try { + if false { Err(25)?; } + Ok::<(), i32>(())?; + 28 + }; + assert_eq!(catch_okay, Ok(28)); + + let catch_from_loop: Result<i32, i32> = try { + for i in 0..10 { + if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; } + } + 22 + }; + assert_eq!(catch_from_loop, Err(5)); + + let cfg_init; + let _res: Result<(), ()> = try { + cfg_init = 5; + }; + assert_eq!(cfg_init, 5); + + let cfg_init_2; + let _res: Result<(), ()> = try { + cfg_init_2 = 6; + Err(())?; + }; + assert_eq!(cfg_init_2, 6); + + let my_string = "test".to_string(); + let res: Result<&str, ()> = try { + // Unfortunately, deref doesn't fire here (#49356) + &my_string[..] + }; + assert_eq!(res, Ok("test")); + + let my_opt: Option<_> = try { () }; + assert_eq!(my_opt, Some(())); + + let my_opt: Option<_> = try { }; + assert_eq!(my_opt, Some(())); +} diff --git a/src/test/ui/try-block/try-is-identifier-edition2015.rs b/src/test/ui/try-block/try-is-identifier-edition2015.rs new file mode 100644 index 000000000..90f56d5fa --- /dev/null +++ b/src/test/ui/try-block/try-is-identifier-edition2015.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(non_camel_case_types)] +// compile-flags: --edition 2015 + +fn main() { + let try = 2; + struct try { try: u32 } + let try: try = try { try }; + assert_eq!(try.try, 2); +} |