diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
commit | 218caa410aa38c29984be31a5229b9fa717560ee (patch) | |
tree | c54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/expr | |
parent | Releasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/expr')
49 files changed, 1306 insertions, 0 deletions
diff --git a/tests/ui/expr/compound-assignment/eval-order.rs b/tests/ui/expr/compound-assignment/eval-order.rs new file mode 100644 index 000000000..658adae19 --- /dev/null +++ b/tests/ui/expr/compound-assignment/eval-order.rs @@ -0,0 +1,76 @@ +// Test evaluation order of operands of the compound assignment operators + +// run-pass + +use std::ops::AddAssign; + +enum Side { + Lhs, + Rhs, +} + +// In the following tests, we place our value into a wrapper type so that we +// can do an element access as the outer place expression. If we just had the +// block expression, it'd be a value expression and not compile. +struct Wrapper<T>(T); + +// Evaluation order for `a op= b` where typeof(a) and typeof(b) are primitives +// is first `b` then `a`. +fn primitive_compound() { + let mut side_order = vec![]; + let mut int = Wrapper(0); + + { + side_order.push(Side::Lhs); + int + }.0 += { + side_order.push(Side::Rhs); + 0 + }; + + assert!(matches!(side_order[..], [Side::Rhs, Side::Lhs])); +} + +// Evaluation order for `a op=b` otherwise is first `a` then `b`. +fn generic_compound<T: AddAssign<T> + Default>() { + let mut side_order = vec![]; + let mut add_assignable: Wrapper<T> = Wrapper(Default::default()); + + { + side_order.push(Side::Lhs); + add_assignable + }.0 += { + side_order.push(Side::Rhs); + Default::default() + }; + + assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs])); +} + +fn custom_compound() { + struct Custom; + + impl AddAssign<()> for Custom { + fn add_assign(&mut self, _: ()) { + // this block purposely left blank + } + } + + let mut side_order = vec![]; + let mut custom = Wrapper(Custom); + + { + side_order.push(Side::Lhs); + custom + }.0 += { + side_order.push(Side::Rhs); + }; + + assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs])); +} + +fn main() { + primitive_compound(); + generic_compound::<i32>(); + custom_compound(); +} diff --git a/tests/ui/expr/if-bot.rs b/tests/ui/expr/if-bot.rs new file mode 100644 index 000000000..0f09db530 --- /dev/null +++ b/tests/ui/expr/if-bot.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let i: isize = if false { panic!() } else { 5 }; + println!("{}", i); +} diff --git a/tests/ui/expr/if/attrs/bad-cfg.rs b/tests/ui/expr/if/attrs/bad-cfg.rs new file mode 100644 index 000000000..3f84929a0 --- /dev/null +++ b/tests/ui/expr/if/attrs/bad-cfg.rs @@ -0,0 +1,5 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression +} diff --git a/tests/ui/expr/if/attrs/bad-cfg.stderr b/tests/ui/expr/if/attrs/bad-cfg.stderr new file mode 100644 index 000000000..8a2890886 --- /dev/null +++ b/tests/ui/expr/if/attrs/bad-cfg.stderr @@ -0,0 +1,8 @@ +error: removing an expression is not supported in this position + --> $DIR/bad-cfg.rs:4:13 + | +LL | let _ = #[cfg(FALSE)] if true {}; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/expr/if/attrs/builtin-if-attr.rs b/tests/ui/expr/if/attrs/builtin-if-attr.rs new file mode 100644 index 000000000..7e2906615 --- /dev/null +++ b/tests/ui/expr/if/attrs/builtin-if-attr.rs @@ -0,0 +1,12 @@ +// check-pass + +fn main() { + #[allow(unused_variables)] + if true { + let a = 1; + } else if false { + let b = 1; + } else { + let c = 1; + } +} diff --git a/tests/ui/expr/if/attrs/cfg-false-if-attr.rs b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs new file mode 100644 index 000000000..1f77a1bb3 --- /dev/null +++ b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs @@ -0,0 +1,43 @@ +// check-pass + +#[cfg(FALSE)] +fn simple_attr() { + #[attr] if true {} + #[allow_warnings] if true {} +} + +#[cfg(FALSE)] +fn if_else_chain() { + #[first_attr] if true { + } else if false { + } else { + } +} + +#[cfg(FALSE)] +fn if_let() { + #[attr] if let Some(_) = Some(true) {} +} + +fn bar() { + #[cfg(FALSE)] + if true { + let x: () = true; // Should not error due to the #[cfg(FALSE)] + } + + #[cfg_attr(not(unset_attr), cfg(FALSE))] + if true { + let a: () = true; // Should not error due to the applied #[cfg(FALSE)] + } +} + +macro_rules! custom_macro { + ($expr:expr) => {} +} + +custom_macro! { + #[attr] if true {} +} + + +fn main() {} diff --git a/tests/ui/expr/if/attrs/else-attrs.rs b/tests/ui/expr/if/attrs/else-attrs.rs new file mode 100644 index 000000000..85da7cf6b --- /dev/null +++ b/tests/ui/expr/if/attrs/else-attrs.rs @@ -0,0 +1,25 @@ +#[cfg(FALSE)] +fn if_else_parse_error() { + if true { + } #[attr] else if false { //~ ERROR expected + } +} + +#[cfg(FALSE)] +fn else_attr_ifparse_error() { + if true { + } else #[attr] if false { //~ ERROR outer attributes are not allowed + } else { + } +} + +#[cfg(FALSE)] +fn else_parse_error() { + if true { + } else if false { + } #[attr] else { //~ ERROR expected + } +} + +fn main() { +} diff --git a/tests/ui/expr/if/attrs/else-attrs.stderr b/tests/ui/expr/if/attrs/else-attrs.stderr new file mode 100644 index 000000000..273337705 --- /dev/null +++ b/tests/ui/expr/if/attrs/else-attrs.stderr @@ -0,0 +1,26 @@ +error: expected expression, found keyword `else` + --> $DIR/else-attrs.rs:4:15 + | +LL | } #[attr] else if false { + | ^^^^ expected expression + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/else-attrs.rs:11:12 + | +LL | } else #[attr] if false { + | _______----_^^^^^^^_- + | | | | + | | | help: remove the attributes + | | the branch belongs to this `else` +LL | | } else { +LL | | } + | |_____- the attributes are attached to this branch + +error: expected expression, found keyword `else` + --> $DIR/else-attrs.rs:20:15 + | +LL | } #[attr] else { + | ^^^^ expected expression + +error: aborting due to 3 previous errors + diff --git a/tests/ui/expr/if/attrs/gate-whole-expr.rs b/tests/ui/expr/if/attrs/gate-whole-expr.rs new file mode 100644 index 000000000..63772d54b --- /dev/null +++ b/tests/ui/expr/if/attrs/gate-whole-expr.rs @@ -0,0 +1,15 @@ +// run-pass + +fn main() { + let x = 1; + + #[cfg(FALSE)] + if false { + x = 2; + } else if true { + x = 3; + } else { + x = 4; + } + assert_eq!(x, 1); +} diff --git a/tests/ui/expr/if/attrs/let-chains-attr.rs b/tests/ui/expr/if/attrs/let-chains-attr.rs new file mode 100644 index 000000000..2cd873114 --- /dev/null +++ b/tests/ui/expr/if/attrs/let-chains-attr.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(let_chains)] + +#[cfg(FALSE)] +fn foo() { + #[attr] + if let Some(_) = Some(true) && let Ok(_) = Ok(1) { + } else if let Some(false) = Some(true) { + } +} + +fn main() {} diff --git a/tests/ui/expr/if/attrs/stmt-expr-gated.rs b/tests/ui/expr/if/attrs/stmt-expr-gated.rs new file mode 100644 index 000000000..38599c8e6 --- /dev/null +++ b/tests/ui/expr/if/attrs/stmt-expr-gated.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = #[deny(warnings)] if true { //~ ERROR attributes on expressions + } else if false { + } else { + }; +} diff --git a/tests/ui/expr/if/attrs/stmt-expr-gated.stderr b/tests/ui/expr/if/attrs/stmt-expr-gated.stderr new file mode 100644 index 000000000..47dac39a9 --- /dev/null +++ b/tests/ui/expr/if/attrs/stmt-expr-gated.stderr @@ -0,0 +1,12 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt-expr-gated.rs:2:13 + | +LL | let _ = #[deny(warnings)] if true { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/expr/if/bad-if-let-suggestion.rs b/tests/ui/expr/if/bad-if-let-suggestion.rs new file mode 100644 index 000000000..a8b2a2830 --- /dev/null +++ b/tests/ui/expr/if/bad-if-let-suggestion.rs @@ -0,0 +1,24 @@ +// FIXME(compiler-errors): This really should suggest `let` on the RHS of the +// `&&` operator, but that's kinda hard to do because of precedence. +// Instead, for now we just make sure not to suggest `if let let`. +fn a() { + if let x = 1 && i = 2 {} + //~^ ERROR cannot find value `i` in this scope + //~| ERROR `let` expressions in this position are unstable + //~| ERROR mismatched types + //~| ERROR `let` expressions are not supported here +} + +fn b() { + if (i + j) = i {} + //~^ ERROR cannot find value `i` in this scope + //~| ERROR cannot find value `i` in this scope + //~| ERROR cannot find value `j` in this scope +} + +fn c() { + if x[0] = 1 {} + //~^ ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/tests/ui/expr/if/bad-if-let-suggestion.stderr b/tests/ui/expr/if/bad-if-let-suggestion.stderr new file mode 100644 index 000000000..3a53a20b4 --- /dev/null +++ b/tests/ui/expr/if/bad-if-let-suggestion.stderr @@ -0,0 +1,74 @@ +error: `let` expressions are not supported here + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:5:21 + | +LL | if let x = 1 && i = 2 {} + | ^ not found in this scope + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:9 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `j` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:13 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:18 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `x` in this scope + --> $DIR/bad-if-let-suggestion.rs:20:8 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if x[0] = 1 {} + | ^ help: a function with a similar name exists: `a` + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^ + | + = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if let x = 1 && i == 2 {} + | + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0425, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/expr-if-panic-fn.rs b/tests/ui/expr/if/expr-if-panic-fn.rs new file mode 100644 index 000000000..36e49785a --- /dev/null +++ b/tests/ui/expr/if/expr-if-panic-fn.rs @@ -0,0 +1,20 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn f() -> ! { + panic!() +} + +fn g() -> isize { + let x = if true { + f() + } else { + 10 + }; + return x; +} + +fn main() { + g(); +} diff --git a/tests/ui/expr/if/expr-if-panic-pass.rs b/tests/ui/expr/if/expr-if-panic-pass.rs new file mode 100644 index 000000000..6069cd835 --- /dev/null +++ b/tests/ui/expr/if/expr-if-panic-pass.rs @@ -0,0 +1,18 @@ +// run-pass + +fn test_if_panic() { + let x = if false { panic!() } else { 10 }; + assert_eq!(x, 10); +} + +fn test_else_panic() { + let x = if true { 10 } else { panic!() }; + assert_eq!(x, 10); +} + +fn test_elseif_panic() { + let x = if false { 0 } else if false { panic!() } else { 10 }; + assert_eq!(x, 10); +} + +pub fn main() { test_if_panic(); test_else_panic(); test_elseif_panic(); } diff --git a/tests/ui/expr/if/expr-if-panic.rs b/tests/ui/expr/if/expr-if-panic.rs new file mode 100644 index 000000000..520ee0870 --- /dev/null +++ b/tests/ui/expr/if/expr-if-panic.rs @@ -0,0 +1,13 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn main() { + let _x = if false { + 0 + } else if true { + panic!() + } else { + 10 + }; +} diff --git a/tests/ui/expr/if/expr-if.rs b/tests/ui/expr/if/expr-if.rs new file mode 100644 index 000000000..2b8474ff4 --- /dev/null +++ b/tests/ui/expr/if/expr-if.rs @@ -0,0 +1,52 @@ +// run-pass +// Tests for if as expressions + +fn test_if() { let rs: bool = if true { true } else { false }; assert!((rs)); } + +fn test_else() { + let rs: bool = if false { false } else { true }; + assert!((rs)); +} + +fn test_elseif1() { + let rs: bool = if true { true } else if true { false } else { false }; + assert!((rs)); +} + +fn test_elseif2() { + let rs: bool = if false { false } else if true { true } else { false }; + assert!((rs)); +} + +fn test_elseif3() { + let rs: bool = if false { false } else if false { false } else { true }; + assert!((rs)); +} + +fn test_inferrence() { + let rs = if true { true } else { false }; + assert!((rs)); +} + +fn test_if_as_if_condition() { + let rs1 = if if false { false } else { true } { true } else { false }; + assert!((rs1)); + let rs2 = if if true { false } else { true } { false } else { true }; + assert!((rs2)); +} + +fn test_if_as_block_result() { + let rs = if true { if false { false } else { true } } else { false }; + assert!((rs)); +} + +pub fn main() { + test_if(); + test_else(); + test_elseif1(); + test_elseif2(); + test_elseif3(); + test_inferrence(); + test_if_as_if_condition(); + test_if_as_block_result(); +} diff --git a/tests/ui/expr/if/if-branch-types.rs b/tests/ui/expr/if/if-branch-types.rs new file mode 100644 index 000000000..c125ba306 --- /dev/null +++ b/tests/ui/expr/if/if-branch-types.rs @@ -0,0 +1,5 @@ +fn main() { + let x = if true { 10i32 } else { 10u32 }; + //~^ ERROR `if` and `else` have incompatible types + //~| expected `i32`, found `u32` +} diff --git a/tests/ui/expr/if/if-branch-types.stderr b/tests/ui/expr/if/if-branch-types.stderr new file mode 100644 index 000000000..d2bba8821 --- /dev/null +++ b/tests/ui/expr/if/if-branch-types.stderr @@ -0,0 +1,16 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-branch-types.rs:2:38 + | +LL | let x = if true { 10i32 } else { 10u32 }; + | ----- ^^^^^ expected `i32`, found `u32` + | | + | expected because of this + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | let x = if true { 10i32 } else { 10i32 }; + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-check-panic.rs b/tests/ui/expr/if/if-check-panic.rs new file mode 100644 index 000000000..037cd427c --- /dev/null +++ b/tests/ui/expr/if/if-check-panic.rs @@ -0,0 +1,25 @@ +// run-fail +// error-pattern:Number is odd +// ignore-emscripten no processes + +fn even(x: usize) -> bool { + if x < 2 { + return false; + } else if x == 2 { + return true; + } else { + return even(x - 2); + } +} + +fn foo(x: usize) { + if even(x) { + println!("{}", x); + } else { + panic!("Number is odd"); + } +} + +fn main() { + foo(3); +} diff --git a/tests/ui/expr/if/if-check.rs b/tests/ui/expr/if/if-check.rs new file mode 100644 index 000000000..6593225e7 --- /dev/null +++ b/tests/ui/expr/if/if-check.rs @@ -0,0 +1,17 @@ +// run-pass + +fn even(x: usize) -> bool { + if x < 2 { + return false; + } else if x == 2 { return true; } else { return even(x - 2); } +} + +fn foo(x: usize) { + if even(x) { + println!("{}", x); + } else { + panic!(); + } +} + +pub fn main() { foo(2); } diff --git a/tests/ui/expr/if/if-cond-bot.rs b/tests/ui/expr/if/if-cond-bot.rs new file mode 100644 index 000000000..bcd114678 --- /dev/null +++ b/tests/ui/expr/if/if-cond-bot.rs @@ -0,0 +1,13 @@ +// run-fail +// error-pattern:quux +// ignore-emscripten no processes + +fn my_err(s: String) -> ! { + println!("{}", s); + panic!("quux"); +} + +fn main() { + if my_err("bye".to_string()) { + } +} diff --git a/tests/ui/expr/if/if-else-type-mismatch.rs b/tests/ui/expr/if/if-else-type-mismatch.rs new file mode 100644 index 000000000..1a0a36df2 --- /dev/null +++ b/tests/ui/expr/if/if-else-type-mismatch.rs @@ -0,0 +1,46 @@ +fn main() { + let _ = if true { + 1i32 + } else { + 2u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { 42i32 } else { 42u32 }; + //~^ ERROR `if` and `else` have incompatible types + let _ = if true { + 3u32; + } else { + 4u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 5u32 + } else { + 6u32; + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 7i32; + } else { + 8u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 9i32 + } else { + 10u32; + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + + } else { + 11u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 12i32 + } else { + + }; + //~^^^ ERROR `if` and `else` have incompatible types +} diff --git a/tests/ui/expr/if/if-else-type-mismatch.stderr b/tests/ui/expr/if/if-else-type-mismatch.stderr new file mode 100644 index 000000000..f1fffdb1e --- /dev/null +++ b/tests/ui/expr/if/if-else-type-mismatch.stderr @@ -0,0 +1,116 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:5:9 + | +LL | let _ = if true { + | _____________- +LL | | 1i32 + | | ---- expected because of this +LL | | } else { +LL | | 2u32 + | | ^^^^ expected `i32`, found `u32` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 2i32 + | ~~~ + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:8:38 + | +LL | let _ = if true { 42i32 } else { 42u32 }; + | ----- ^^^^^ expected `i32`, found `u32` + | | + | expected because of this + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | let _ = if true { 42i32 } else { 42i32 }; + | ~~~ + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:13:9 + | +LL | let _ = if true { + | _____________- +LL | | 3u32; + | | ----- + | | | | + | | | help: consider removing this semicolon + | | expected because of this +LL | | } else { +LL | | 4u32 + | | ^^^^ expected `()`, found `u32` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:19:9 + | +LL | let _ = if true { + | _____________- +LL | | 5u32 + | | ---- expected because of this +LL | | } else { +LL | | 6u32; + | | ^^^^- + | | | | + | | | help: consider removing this semicolon + | | expected `u32`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:25:9 + | +LL | let _ = if true { + | _____________- +LL | | 7i32; + | | ----- expected because of this +LL | | } else { +LL | | 8u32 + | | ^^^^ expected `()`, found `u32` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:31:9 + | +LL | let _ = if true { + | _____________- +LL | | 9i32 + | | ---- expected because of this +LL | | } else { +LL | | 10u32; + | | ^^^^^^ expected `i32`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:37:9 + | +LL | let _ = if true { + | _____________________- +LL | | +LL | | } else { + | |_____- expected because of this +LL | 11u32 + | ^^^^^ expected `()`, found `u32` + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:42:12 + | +LL | let _ = if true { + | ------- `if` and `else` have incompatible types +LL | 12i32 + | ----- expected because of this +LL | } else { + | ____________^ +LL | | +LL | | }; + | |_____^ expected `i32`, found `()` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-let-arm-types.rs b/tests/ui/expr/if/if-let-arm-types.rs new file mode 100644 index 000000000..1e8260a01 --- /dev/null +++ b/tests/ui/expr/if/if-let-arm-types.rs @@ -0,0 +1,11 @@ +fn main() { + if let Some(b) = None { + //~^ NOTE `if` and `else` have incompatible types + () + //~^ NOTE expected because of this + } else { + 1 + }; + //~^^ ERROR: `if` and `else` have incompatible types + //~| NOTE expected `()`, found integer +} diff --git a/tests/ui/expr/if/if-let-arm-types.stderr b/tests/ui/expr/if/if-let-arm-types.stderr new file mode 100644 index 000000000..b40a0f479 --- /dev/null +++ b/tests/ui/expr/if/if-let-arm-types.stderr @@ -0,0 +1,17 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-let-arm-types.rs:7:9 + | +LL | / if let Some(b) = None { +LL | | +LL | | () + | | -- expected because of this +LL | | +LL | | } else { +LL | | 1 + | | ^ expected `()`, found integer +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-let.rs b/tests/ui/expr/if/if-let.rs new file mode 100644 index 000000000..7fdd2be95 --- /dev/null +++ b/tests/ui/expr/if/if-let.rs @@ -0,0 +1,49 @@ +// check-pass + +fn macros() { + macro_rules! foo { + ($p:pat, $e:expr, $b:block) => {{ + if let $p = $e $b + //~^ WARN irrefutable `if let` + //~| WARN irrefutable `if let` + }} + } + macro_rules! bar{ + ($p:pat, $e:expr, $b:block) => {{ + foo!($p, $e, $b) + }} + } + + foo!(a, 1, { + println!("irrefutable pattern"); + }); + bar!(a, 1, { + println!("irrefutable pattern"); + }); +} + +pub fn main() { + if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } + + if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } else if true { + println!("else-if in irrefutable `if let`"); + } else { + println!("else in irrefutable `if let`"); + } + + if let 1 = 2 { + println!("refutable pattern"); + } else if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } + + if true { + println!("if"); + } else if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } +} diff --git a/tests/ui/expr/if/if-let.stderr b/tests/ui/expr/if/if-let.stderr new file mode 100644 index 000000000..c4bba3cb1 --- /dev/null +++ b/tests/ui/expr/if/if-let.stderr @@ -0,0 +1,69 @@ +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:6:16 + | +LL | if let $p = $e $b + | ^^^ +... +LL | / foo!(a, 1, { +LL | | println!("irrefutable pattern"); +LL | | }); + | |______- in this macro invocation + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:6:16 + | +LL | if let $p = $e $b + | ^^^ +... +LL | / bar!(a, 1, { +LL | | println!("irrefutable pattern"); +LL | | }); + | |______- in this macro invocation + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: this warning originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:26:8 + | +LL | if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:30:8 + | +LL | if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:40:15 + | +LL | } else if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:46:15 + | +LL | } else if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: 6 warnings emitted + diff --git a/tests/ui/expr/if/if-loop.rs b/tests/ui/expr/if/if-loop.rs new file mode 100644 index 000000000..06d0bdf45 --- /dev/null +++ b/tests/ui/expr/if/if-loop.rs @@ -0,0 +1,8 @@ +// check-pass + +// This used to ICE because the "if" being unreachable was not handled correctly +fn err() { + if loop {} {} +} + +fn main() {} diff --git a/tests/ui/expr/if/if-no-match-bindings.rs b/tests/ui/expr/if/if-no-match-bindings.rs new file mode 100644 index 000000000..ca3df0fdd --- /dev/null +++ b/tests/ui/expr/if/if-no-match-bindings.rs @@ -0,0 +1,28 @@ +// Checks for `if` expressions with respect to default match bindings. +// Specifically, we do not accept `if cond { ... }` where `cond: &mut? bool`. +// Meanwhile, `match cond { true => ..., _ => ... }` does accept that. + +// FIXME(@rust-lang/lang-team): consider relaxing this? + +fn b_ref<'a>() -> &'a bool { &true } +fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + +fn main() { + // This is OK: + match b_ref() { true => {}, _ => {} } + match b_mut_ref() { true => {}, _ => {} } + match &true { true => {}, _ => {} } + match &mut true { true => {}, _ => {} } + + // This is NOT: + if b_ref() {} //~ ERROR mismatched types [E0308] + if b_mut_ref() {} //~ ERROR mismatched types [E0308] + if &true {} //~ ERROR mismatched types [E0308] + if &mut true {} //~ ERROR mismatched types [E0308] + + // This is also NOT: + while b_ref() {} //~ ERROR mismatched types [E0308] + while b_mut_ref() {} //~ ERROR mismatched types [E0308] + while &true {} //~ ERROR mismatched types [E0308] + while &mut true {} //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr new file mode 100644 index 000000000..737a5d604 --- /dev/null +++ b/tests/ui/expr/if/if-no-match-bindings.stderr @@ -0,0 +1,95 @@ +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:18:8 + | +LL | if b_ref() {} + | ^^^^^^^ expected `bool`, found `&bool` + | +help: consider dereferencing the borrow + | +LL | if *b_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:19:8 + | +LL | if b_mut_ref() {} + | ^^^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider dereferencing the borrow + | +LL | if *b_mut_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:20:8 + | +LL | if &true {} + | ^^^^^ expected `bool`, found `&bool` + | +help: consider removing the borrow + | +LL - if &true {} +LL + if true {} + | + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:21:8 + | +LL | if &mut true {} + | ^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider removing the borrow + | +LL - if &mut true {} +LL + if true {} + | + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:24:11 + | +LL | while b_ref() {} + | ^^^^^^^ expected `bool`, found `&bool` + | +help: consider dereferencing the borrow + | +LL | while *b_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:25:11 + | +LL | while b_mut_ref() {} + | ^^^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider dereferencing the borrow + | +LL | while *b_mut_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:26:11 + | +LL | while &true {} + | ^^^^^ expected `bool`, found `&bool` + | +help: consider removing the borrow + | +LL - while &true {} +LL + while true {} + | + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:27:11 + | +LL | while &mut true {} + | ^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider removing the borrow + | +LL - while &mut true {} +LL + while true {} + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-ret.rs b/tests/ui/expr/if/if-ret.rs new file mode 100644 index 000000000..896072ce7 --- /dev/null +++ b/tests/ui/expr/if/if-ret.rs @@ -0,0 +1,8 @@ +// run-pass + +#![allow(unused_parens)] +// pretty-expanded FIXME #23616 + +fn foo() { if (return) { } } //~ WARNING unreachable block in `if` + +pub fn main() { foo(); } diff --git a/tests/ui/expr/if/if-ret.stderr b/tests/ui/expr/if/if-ret.stderr new file mode 100644 index 000000000..8ced271aa --- /dev/null +++ b/tests/ui/expr/if/if-ret.stderr @@ -0,0 +1,12 @@ +warning: unreachable block in `if` or `while` expression + --> $DIR/if-ret.rs:6:24 + | +LL | fn foo() { if (return) { } } + | -------- ^^^ unreachable block in `if` or `while` expression + | | + | any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/expr/if/if-typeck.rs b/tests/ui/expr/if/if-typeck.rs new file mode 100644 index 000000000..d8c262bd6 --- /dev/null +++ b/tests/ui/expr/if/if-typeck.rs @@ -0,0 +1,10 @@ +// error-pattern:mismatched types +// issue #513 + +fn f() { } + +fn main() { + + // f is not a bool + if f { } +} diff --git a/tests/ui/expr/if/if-typeck.stderr b/tests/ui/expr/if/if-typeck.stderr new file mode 100644 index 000000000..74ed0ed0a --- /dev/null +++ b/tests/ui/expr/if/if-typeck.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/if-typeck.rs:9:8 + | +LL | if f { } + | ^ expected `bool`, found fn item + | + = note: expected type `bool` + found fn item `fn() {f}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-without-block.rs b/tests/ui/expr/if/if-without-block.rs new file mode 100644 index 000000000..5add9dfda --- /dev/null +++ b/tests/ui/expr/if/if-without-block.rs @@ -0,0 +1,7 @@ +fn main() { + let n = 1; + if 5 == { + //~^ ERROR this `if` expression is missing a block after the condition + println!("five"); + } +} diff --git a/tests/ui/expr/if/if-without-block.stderr b/tests/ui/expr/if/if-without-block.stderr new file mode 100644 index 000000000..2d1ee04ce --- /dev/null +++ b/tests/ui/expr/if/if-without-block.stderr @@ -0,0 +1,14 @@ +error: this `if` expression is missing a block after the condition + --> $DIR/if-without-block.rs:3:5 + | +LL | if 5 == { + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/if-without-block.rs:3:8 + | +LL | if 5 == { + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/expr/if/if-without-else-as-fn-expr.rs b/tests/ui/expr/if/if-without-else-as-fn-expr.rs new file mode 100644 index 000000000..19fbfb27b --- /dev/null +++ b/tests/ui/expr/if/if-without-else-as-fn-expr.rs @@ -0,0 +1,49 @@ +fn foo(bar: usize) -> usize { + if bar % 5 == 0 { + return 3; + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +fn foo2(bar: usize) -> usize { + let x: usize = if bar % 5 == 0 { + return 3; + }; + //~^^^ ERROR `if` may be missing an `else` clause + x +} + +fn foo3(bar: usize) -> usize { + if bar % 5 == 0 { + 3 + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +fn foo_let(bar: usize) -> usize { + if let 0 = 1 { + return 3; + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +fn foo2_let(bar: usize) -> usize { + let x: usize = if let 0 = 1 { + return 3; + }; + //~^^^ ERROR `if` may be missing an `else` clause + x +} + +fn foo3_let(bar: usize) -> usize { + if let 0 = 1 { + 3 + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +// FIXME(60254): deduplicate first error in favor of second. + +fn main() { + let _ = foo(1); +} diff --git a/tests/ui/expr/if/if-without-else-as-fn-expr.stderr b/tests/ui/expr/if/if-without-else-as-fn-expr.stderr new file mode 100644 index 000000000..4daf27493 --- /dev/null +++ b/tests/ui/expr/if/if-without-else-as-fn-expr.stderr @@ -0,0 +1,83 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:2:5 + | +LL | fn foo(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if bar % 5 == 0 { +LL | | return 3; +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:9:20 + | +LL | let x: usize = if bar % 5 == 0 { + | _________-__________^ + | | | + | | expected because of this assignment +LL | | return 3; +LL | | }; + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:17:5 + | +LL | fn foo3(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if bar % 5 == 0 { +LL | | 3 +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:24:5 + | +LL | fn foo_let(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if let 0 = 1 { +LL | | return 3; +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:31:20 + | +LL | let x: usize = if let 0 = 1 { + | _________-__________^ + | | | + | | expected because of this assignment +LL | | return 3; +LL | | }; + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:39:5 + | +LL | fn foo3_let(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if let 0 = 1 { +LL | | 3 +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/if/if-without-else-result.rs b/tests/ui/expr/if/if-without-else-result.rs new file mode 100644 index 000000000..95604758a --- /dev/null +++ b/tests/ui/expr/if/if-without-else-result.rs @@ -0,0 +1,6 @@ +fn main() { + let a = if true { true }; + //~^ ERROR `if` may be missing an `else` clause [E0317] + //~| expected `bool`, found `()` + println!("{}", a); +} diff --git a/tests/ui/expr/if/if-without-else-result.stderr b/tests/ui/expr/if/if-without-else-result.stderr new file mode 100644 index 000000000..317faf7c6 --- /dev/null +++ b/tests/ui/expr/if/if-without-else-result.stderr @@ -0,0 +1,15 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-result.rs:2:13 + | +LL | let a = if true { true }; + | ^^^^^^^^^^----^^ + | | | + | | found here + | expected `bool`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/if/issue-4201.rs b/tests/ui/expr/if/issue-4201.rs new file mode 100644 index 000000000..59c465b9e --- /dev/null +++ b/tests/ui/expr/if/issue-4201.rs @@ -0,0 +1,9 @@ +fn main() { + let a = if true { + 0 + } else if false { +//~^ ERROR `if` may be missing an `else` clause +//~| expected integer, found `()` + 1 + }; +} diff --git a/tests/ui/expr/if/issue-4201.stderr b/tests/ui/expr/if/issue-4201.stderr new file mode 100644 index 000000000..612fe7764 --- /dev/null +++ b/tests/ui/expr/if/issue-4201.stderr @@ -0,0 +1,18 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/issue-4201.rs:4:12 + | +LL | } else if false { + | ____________^ +LL | | +LL | | +LL | | 1 + | | - found here +LL | | }; + | |_____^ expected integer, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed b/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed new file mode 100644 index 000000000..c50b9a12b --- /dev/null +++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed @@ -0,0 +1,19 @@ +// This snippet ensures that no attempt to recover on a semicolon instead of +// comma is made next to a closure body. +// +// If this recovery happens, then plenty of errors are emitted. Here, we expect +// only one error. +// +// This is part of issue #88065: +// https://github.com/rust-lang/rust/issues/88065 + +// run-rustfix + +fn main() { + let num = 5; + (1..num).reduce(|a, b| { + //~^ ERROR: closure bodies that contain statements must be surrounded by braces + println!("{}", a); + a * b + }).unwrap(); +} diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.rs b/tests/ui/expr/malformed_closure/missing_braces_around_block.rs new file mode 100644 index 000000000..58c81f3a6 --- /dev/null +++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.rs @@ -0,0 +1,19 @@ +// This snippet ensures that no attempt to recover on a semicolon instead of +// comma is made next to a closure body. +// +// If this recovery happens, then plenty of errors are emitted. Here, we expect +// only one error. +// +// This is part of issue #88065: +// https://github.com/rust-lang/rust/issues/88065 + +// run-rustfix + +fn main() { + let num = 5; + (1..num).reduce(|a, b| + //~^ ERROR: closure bodies that contain statements must be surrounded by braces + println!("{}", a); + a * b + ).unwrap(); +} diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr b/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr new file mode 100644 index 000000000..dac9a8cfc --- /dev/null +++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr @@ -0,0 +1,38 @@ +error: closure bodies that contain statements must be surrounded by braces + --> $DIR/missing_braces_around_block.rs:14:26 + | +LL | (1..num).reduce(|a, b| + | ^ +... +LL | ).unwrap(); + | ^ + | +note: statement found outside of a block + --> $DIR/missing_braces_around_block.rs:16:26 + | +LL | println!("{}", a); + | -----------------^ this `;` turns the preceding closure into a statement + | | + | this expression is a statement because of the trailing semicolon +note: the closure body may be incorrectly delimited + --> $DIR/missing_braces_around_block.rs:14:21 + | +LL | (1..num).reduce(|a, b| + | _____________________^ +LL | | +LL | | println!("{}", a); + | |_________________________^ this is the parsed closure... +LL | a * b +LL | ).unwrap(); + | - ...but likely you meant the closure to end here +help: try adding braces + | +LL ~ (1..num).reduce(|a, b| { +LL | +LL | println!("{}", a); +LL | a * b +LL ~ }).unwrap(); + | + +error: aborting due to previous error + diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure.rs b/tests/ui/expr/malformed_closure/ruby_style_closure.rs new file mode 100644 index 000000000..fdec072b8 --- /dev/null +++ b/tests/ui/expr/malformed_closure/ruby_style_closure.rs @@ -0,0 +1,15 @@ +// Part of issue #27300. +// The problem here is that ruby-style closures are parsed as blocks whose +// first statement is a closure. See the issue for more details: +// https://github.com/rust-lang/rust/issues/27300 + +// Note: this test represents what the compiler currently emits. The error +// message will be improved later. + +fn main() { + let p = Some(45).and_then({ + |x| println!("doubling {}", x); + Some(x * 2) + //~^ ERROR: cannot find value `x` in this scope + }); +} diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure.stderr b/tests/ui/expr/malformed_closure/ruby_style_closure.stderr new file mode 100644 index 000000000..e8b34121b --- /dev/null +++ b/tests/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/ruby_style_closure.rs:12:14 + | +LL | Some(x * 2) + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. |