about summary refs log tree commit diff
path: root/src/test/ui/expr
diff options
context:
space:
mode:
authorHavvy (Ryan Scheel) <ryan.havvy@gmail.com>2020-11-24 17:35:53 -0800
committerHavvy (Ryan Scheel) <ryan.havvy@gmail.com>2020-11-24 17:35:53 -0800
commit37b97f095ccbb7dcea7c678f1bbc4210e72f4489 (patch)
treeb874d144d69a721261eb38647c430bd26f7f0f0d /src/test/ui/expr
parent1c389ffeff814726dec325f0f2b0c99107df2673 (diff)
downloadrust-37b97f095ccbb7dcea7c678f1bbc4210e72f4489.tar.gz
rust-37b97f095ccbb7dcea7c678f1bbc4210e72f4489.zip
Move src/test/ui/if to src/test/ui/expr/if
Diffstat (limited to 'src/test/ui/expr')
-rw-r--r--src/test/ui/expr/if/expr-if-panic-fn.rs20
-rw-r--r--src/test/ui/expr/if/expr-if-panic.rs13
-rw-r--r--src/test/ui/expr/if/if-branch-types.rs5
-rw-r--r--src/test/ui/expr/if/if-branch-types.stderr11
-rw-r--r--src/test/ui/expr/if/if-check-panic.rs25
-rw-r--r--src/test/ui/expr/if/if-cond-bot.rs13
-rw-r--r--src/test/ui/expr/if/if-let-arm-types.rs11
-rw-r--r--src/test/ui/expr/if/if-let-arm-types.stderr17
-rw-r--r--src/test/ui/expr/if/if-let.rs49
-rw-r--r--src/test/ui/expr/if/if-let.stderr67
-rw-r--r--src/test/ui/expr/if/if-loop.rs8
-rw-r--r--src/test/ui/expr/if/if-no-match-bindings.rs28
-rw-r--r--src/test/ui/expr/if/if-no-match-bindings.stderr75
-rw-r--r--src/test/ui/expr/if/if-typeck.rs10
-rw-r--r--src/test/ui/expr/if/if-typeck.stderr12
-rw-r--r--src/test/ui/expr/if/if-without-block.rs9
-rw-r--r--src/test/ui/expr/if/if-without-block.stderr13
-rw-r--r--src/test/ui/expr/if/if-without-else-as-fn-expr.rs49
-rw-r--r--src/test/ui/expr/if/if-without-else-as-fn-expr.stderr83
-rw-r--r--src/test/ui/expr/if/if-without-else-result.rs6
-rw-r--r--src/test/ui/expr/if/if-without-else-result.stderr15
-rw-r--r--src/test/ui/expr/if/ifmt-bad-arg.rs94
-rw-r--r--src/test/ui/expr/if/ifmt-bad-arg.stderr327
-rw-r--r--src/test/ui/expr/if/ifmt-bad-format-args.rs4
-rw-r--r--src/test/ui/expr/if/ifmt-bad-format-args.stderr21
-rw-r--r--src/test/ui/expr/if/ifmt-unimpl.rs4
-rw-r--r--src/test/ui/expr/if/ifmt-unimpl.stderr13
-rw-r--r--src/test/ui/expr/if/ifmt-unknown-trait.rs4
-rw-r--r--src/test/ui/expr/if/ifmt-unknown-trait.stderr19
29 files changed, 1025 insertions, 0 deletions
diff --git a/src/test/ui/expr/if/expr-if-panic-fn.rs b/src/test/ui/expr/if/expr-if-panic-fn.rs
new file mode 100644
index 00000000000..36e49785a49
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/expr-if-panic.rs b/src/test/ui/expr/if/expr-if-panic.rs
new file mode 100644
index 00000000000..520ee0870ee
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-branch-types.rs b/src/test/ui/expr/if/if-branch-types.rs
new file mode 100644
index 00000000000..c125ba30606
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-branch-types.stderr b/src/test/ui/expr/if/if-branch-types.stderr
new file mode 100644
index 00000000000..14f02163a83
--- /dev/null
+++ b/src/test/ui/expr/if/if-branch-types.stderr
@@ -0,0 +1,11 @@
+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
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/expr/if/if-check-panic.rs b/src/test/ui/expr/if/if-check-panic.rs
new file mode 100644
index 00000000000..037cd427ccf
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-cond-bot.rs b/src/test/ui/expr/if/if-cond-bot.rs
new file mode 100644
index 00000000000..bcd11467852
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-let-arm-types.rs b/src/test/ui/expr/if/if-let-arm-types.rs
new file mode 100644
index 00000000000..1e8260a017d
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-let-arm-types.stderr b/src/test/ui/expr/if/if-let-arm-types.stderr
new file mode 100644
index 00000000000..b40a0f479d3
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-let.rs b/src/test/ui/expr/if/if-let.rs
new file mode 100644
index 00000000000..2ab0f9fed3f
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-let.stderr b/src/test/ui/expr/if/if-let.stderr
new file mode 100644
index 00000000000..ee2b78af3b8
--- /dev/null
+++ b/src/test/ui/expr/if/if-let.stderr
@@ -0,0 +1,67 @@
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:6:13
+   |
+LL |               if let $p = $e $b
+   |               ^^^^^^^^^^^^^^^^^
+...
+LL | /     foo!(a, 1, {
+LL | |         println!("irrefutable pattern");
+LL | |     });
+   | |_______- in this macro invocation
+   |
+   = note: `#[warn(irrefutable_let_patterns)]` on by default
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:6:13
+   |
+LL |               if let $p = $e $b
+   |               ^^^^^^^^^^^^^^^^^
+...
+LL | /     bar!(a, 1, {
+LL | |         println!("irrefutable pattern");
+LL | |     });
+   | |_______- in this macro invocation
+   |
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:26:5
+   |
+LL | /     if let a = 1 {
+LL | |         println!("irrefutable pattern");
+LL | |     }
+   | |_____^
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:30:5
+   |
+LL | /     if let a = 1 {
+LL | |         println!("irrefutable pattern");
+LL | |     } else if true {
+LL | |         println!("else-if in irrefutable if-let");
+LL | |     } else {
+LL | |         println!("else in irrefutable if-let");
+LL | |     }
+   | |_____^
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:40:12
+   |
+LL |       } else if let a = 1 {
+   |  ____________^
+LL | |         println!("irrefutable pattern");
+LL | |     }
+   | |_____^
+
+warning: irrefutable if-let pattern
+  --> $DIR/if-let.rs:46:12
+   |
+LL |       } else if let a = 1 {
+   |  ____________^
+LL | |         println!("irrefutable pattern");
+LL | |     }
+   | |_____^
+
+warning: 6 warnings emitted
+
diff --git a/src/test/ui/expr/if/if-loop.rs b/src/test/ui/expr/if/if-loop.rs
new file mode 100644
index 00000000000..06d0bdf456c
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-no-match-bindings.rs b/src/test/ui/expr/if/if-no-match-bindings.rs
new file mode 100644
index 00000000000..ca3df0fdde4
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-no-match-bindings.stderr b/src/test/ui/expr/if/if-no-match-bindings.stderr
new file mode 100644
index 00000000000..3f382e023a7
--- /dev/null
+++ b/src/test/ui/expr/if/if-no-match-bindings.stderr
@@ -0,0 +1,75 @@
+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: `*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: `*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: `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: `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: `*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: `*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: `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: `true`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/expr/if/if-typeck.rs b/src/test/ui/expr/if/if-typeck.rs
new file mode 100644
index 00000000000..d8c262bd6b3
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-typeck.stderr b/src/test/ui/expr/if/if-typeck.stderr
new file mode 100644
index 00000000000..74ed0ed0ae6
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-without-block.rs b/src/test/ui/expr/if/if-without-block.rs
new file mode 100644
index 00000000000..8a4c59f3261
--- /dev/null
+++ b/src/test/ui/expr/if/if-without-block.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let n = 1;
+    if 5 == {
+    //~^ NOTE this `if` expression has a condition, but no block
+        println!("five");
+    }
+}
+//~^ ERROR expected `{`, found `}`
+//~| NOTE expected `{`
diff --git a/src/test/ui/expr/if/if-without-block.stderr b/src/test/ui/expr/if/if-without-block.stderr
new file mode 100644
index 00000000000..ee2bb62e2bb
--- /dev/null
+++ b/src/test/ui/expr/if/if-without-block.stderr
@@ -0,0 +1,13 @@
+error: expected `{`, found `}`
+  --> $DIR/if-without-block.rs:7:1
+   |
+LL |     if 5 == {
+   |     -- this `if` expression has a condition, but no block
+...
+LL | }
+   | ^ expected `{`
+   |
+   = help: maybe you forgot the right operand of the condition?
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/expr/if/if-without-else-as-fn-expr.rs b/src/test/ui/expr/if/if-without-else-as-fn-expr.rs
new file mode 100644
index 00000000000..19fbfb27ba6
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-without-else-as-fn-expr.stderr b/src/test/ui/expr/if/if-without-else-as-fn-expr.stderr
new file mode 100644
index 00000000000..4daf27493c1
--- /dev/null
+++ b/src/test/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/src/test/ui/expr/if/if-without-else-result.rs b/src/test/ui/expr/if/if-without-else-result.rs
new file mode 100644
index 00000000000..cf84a99e53f
--- /dev/null
+++ b/src/test/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 `()`, found `bool`
+    println!("{}", a);
+}
diff --git a/src/test/ui/expr/if/if-without-else-result.stderr b/src/test/ui/expr/if/if-without-else-result.stderr
new file mode 100644
index 00000000000..821635d3768
--- /dev/null
+++ b/src/test/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 `()`, found `bool`
+   |
+   = 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/src/test/ui/expr/if/ifmt-bad-arg.rs b/src/test/ui/expr/if/ifmt-bad-arg.rs
new file mode 100644
index 00000000000..a0b0a8fb985
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-bad-arg.rs
@@ -0,0 +1,94 @@
+fn main() {
+    // bad arguments to the format! call
+
+    // bad number of arguments, see #44954 (originally #15780)
+
+    format!("{}");
+    //~^ ERROR: 1 positional argument in format string, but no arguments were given
+
+    format!("{1}", 1);
+    //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+    //~^^ ERROR: argument never used
+
+    format!("{} {}");
+    //~^ ERROR: 2 positional arguments in format string, but no arguments were given
+
+    format!("{0} {1}", 1);
+    //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+
+    format!("{0} {1} {2}", 1, 2);
+    //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+
+    format!("{} {value} {} {}", 1, value=2);
+    //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+    format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+    //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+
+    format!("{} {foo} {} {bar} {}", 1, 2, 3);
+    //~^ ERROR: there is no argument named `foo`
+    //~^^ ERROR: there is no argument named `bar`
+
+    format!("{foo}");                //~ ERROR: no argument named `foo`
+    format!("", 1, 2);               //~ ERROR: multiple unused formatting arguments
+    format!("{}", 1, 2);             //~ ERROR: argument never used
+    format!("{1}", 1, 2);            //~ ERROR: argument never used
+    format!("{}", 1, foo=2);         //~ ERROR: named argument never used
+    format!("{foo}", 1, foo=2);      //~ ERROR: argument never used
+    format!("", foo=2);              //~ ERROR: named argument never used
+    format!("{} {}", 1, 2, foo=1, bar=2);  //~ ERROR: multiple unused formatting arguments
+
+    format!("{foo}", foo=1, foo=2);  //~ ERROR: duplicate argument
+    format!("{foo} {} {}", foo=1, 2);   //~ ERROR: positional arguments cannot follow
+
+    // bad named arguments, #35082
+
+    format!("{valuea} {valueb}", valuea=5, valuec=7);
+    //~^ ERROR there is no argument named `valueb`
+    //~^^ ERROR named argument never used
+
+    // bad syntax of the format string
+
+    format!("{"); //~ ERROR: expected `'}'` but string was terminated
+
+    format!("foo } bar"); //~ ERROR: unmatched `}` found
+    format!("foo }"); //~ ERROR: unmatched `}` found
+
+    format!("foo %s baz", "bar"); //~ ERROR: argument never used
+
+    format!(r##"
+
+        {foo}
+
+    "##);
+    //~^^^ ERROR: there is no argument named `foo`
+
+    // bad syntax in format string with multiple newlines, #53836
+    format!("first number: {}
+second number: {}
+third number: {}
+fourth number: {}
+fifth number: {}
+sixth number: {}
+seventh number: {}
+eighth number: {}
+ninth number: {
+tenth number: {}",
+        1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    //~^^ ERROR: invalid format string
+    println!("{} {:.*} {}", 1, 3.2, 4);
+    //~^ ERROR 4 positional arguments in format string, but there are 3 arguments
+    //~| ERROR mismatched types
+    println!("{} {:07$.*} {}", 1, 3.2, 4);
+    //~^ ERROR 4 positional arguments in format string, but there are 3 arguments
+    //~| ERROR mismatched types
+    println!("{} {:07$} {}", 1, 3.2, 4);
+    //~^ ERROR invalid reference to positional argument 7 (there are 3 arguments)
+    println!("{:foo}", 1); //~ ERROR unknown format trait `foo`
+    println!("{5} {:4$} {6:7$}", 1);
+    //~^ ERROR invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument)
+
+    // We used to ICE here because we tried to unconditionally access the first argument, which
+    // doesn't exist.
+    println!("{:.*}");
+    //~^ ERROR 2 positional arguments in format string, but no arguments were given
+}
diff --git a/src/test/ui/expr/if/ifmt-bad-arg.stderr b/src/test/ui/expr/if/ifmt-bad-arg.stderr
new file mode 100644
index 00000000000..0ff478826f7
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-bad-arg.stderr
@@ -0,0 +1,327 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/ifmt-bad-arg.rs:6:14
+   |
+LL |     format!("{}");
+   |              ^^
+
+error: invalid reference to positional argument 1 (there is 1 argument)
+  --> $DIR/ifmt-bad-arg.rs:9:14
+   |
+LL |     format!("{1}", 1);
+   |              ^^^
+   |
+   = note: positional arguments are zero-based
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:9:20
+   |
+LL |     format!("{1}", 1);
+   |             -----  ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: 2 positional arguments in format string, but no arguments were given
+  --> $DIR/ifmt-bad-arg.rs:13:14
+   |
+LL |     format!("{} {}");
+   |              ^^ ^^
+
+error: invalid reference to positional argument 1 (there is 1 argument)
+  --> $DIR/ifmt-bad-arg.rs:16:18
+   |
+LL |     format!("{0} {1}", 1);
+   |                  ^^^
+   |
+   = note: positional arguments are zero-based
+
+error: invalid reference to positional argument 2 (there are 2 arguments)
+  --> $DIR/ifmt-bad-arg.rs:19:22
+   |
+LL |     format!("{0} {1} {2}", 1, 2);
+   |                      ^^^
+   |
+   = note: positional arguments are zero-based
+
+error: invalid reference to positional argument 2 (there are 2 arguments)
+  --> $DIR/ifmt-bad-arg.rs:22:28
+   |
+LL |     format!("{} {value} {} {}", 1, value=2);
+   |                            ^^
+   |
+   = note: positional arguments are zero-based
+
+error: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+  --> $DIR/ifmt-bad-arg.rs:24:38
+   |
+LL |     format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+   |                                      ^^ ^^ ^^
+   |
+   = note: positional arguments are zero-based
+
+error: there is no argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:27:17
+   |
+LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
+   |                 ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
+
+error: there is no argument named `bar`
+  --> $DIR/ifmt-bad-arg.rs:27:26
+   |
+LL |     format!("{} {foo} {} {bar} {}", 1, 2, 3);
+   |                          ^^^^^
+   |
+   = help: if you intended to capture `bar` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
+
+error: there is no argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:31:14
+   |
+LL |     format!("{foo}");
+   |              ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
+
+error: multiple unused formatting arguments
+  --> $DIR/ifmt-bad-arg.rs:32:17
+   |
+LL |     format!("", 1, 2);
+   |             --  ^  ^ argument never used
+   |             |   |
+   |             |   argument never used
+   |             multiple missing formatting specifiers
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:33:22
+   |
+LL |     format!("{}", 1, 2);
+   |             ----     ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:34:20
+   |
+LL |     format!("{1}", 1, 2);
+   |             -----  ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: named argument never used
+  --> $DIR/ifmt-bad-arg.rs:35:26
+   |
+LL |     format!("{}", 1, foo=2);
+   |             ----         ^ named argument never used
+   |             |
+   |             formatting specifier missing
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:36:22
+   |
+LL |     format!("{foo}", 1, foo=2);
+   |             -------  ^ argument never used
+   |             |
+   |             formatting specifier missing
+
+error: named argument never used
+  --> $DIR/ifmt-bad-arg.rs:37:21
+   |
+LL |     format!("", foo=2);
+   |             --      ^ named argument never used
+   |             |
+   |             formatting specifier missing
+
+error: multiple unused formatting arguments
+  --> $DIR/ifmt-bad-arg.rs:38:32
+   |
+LL |     format!("{} {}", 1, 2, foo=1, bar=2);
+   |             -------            ^      ^ named argument never used
+   |             |                  |
+   |             |                  named argument never used
+   |             multiple missing formatting specifiers
+
+error: duplicate argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:40:33
+   |
+LL |     format!("{foo}", foo=1, foo=2);
+   |                          -      ^ duplicate argument
+   |                          |
+   |                          previously here
+
+error: positional arguments cannot follow named arguments
+  --> $DIR/ifmt-bad-arg.rs:41:35
+   |
+LL |     format!("{foo} {} {}", foo=1, 2);
+   |                                -  ^ positional arguments must be before named arguments
+   |                                |
+   |                                named argument
+
+error: there is no argument named `valueb`
+  --> $DIR/ifmt-bad-arg.rs:45:23
+   |
+LL |     format!("{valuea} {valueb}", valuea=5, valuec=7);
+   |                       ^^^^^^^^
+   |
+   = help: if you intended to capture `valueb` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
+
+error: named argument never used
+  --> $DIR/ifmt-bad-arg.rs:45:51
+   |
+LL |     format!("{valuea} {valueb}", valuea=5, valuec=7);
+   |             -------------------                   ^ named argument never used
+   |             |
+   |             formatting specifier missing
+
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/ifmt-bad-arg.rs:51:15
+   |
+LL |     format!("{");
+   |              -^ expected `'}'` in format string
+   |              |
+   |              because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/ifmt-bad-arg.rs:53:18
+   |
+LL |     format!("foo } bar");
+   |                  ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/ifmt-bad-arg.rs:54:18
+   |
+LL |     format!("foo }");
+   |                  ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: argument never used
+  --> $DIR/ifmt-bad-arg.rs:56:27
+   |
+LL |     format!("foo %s baz", "bar");
+   |                  --       ^^^^^ argument never used
+   |                  |
+   |                  help: format specifiers use curly braces: `{}`
+   |
+   = note: printf formatting not supported; see the documentation for `std::fmt`
+
+error: there is no argument named `foo`
+  --> $DIR/ifmt-bad-arg.rs:60:9
+   |
+LL |         {foo}
+   |         ^^^^^
+   |
+   = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes
+
+error: invalid format string: expected `'}'`, found `'t'`
+  --> $DIR/ifmt-bad-arg.rs:75:1
+   |
+LL | ninth number: {
+   |               - because of this opening brace
+LL | tenth number: {}",
+   | ^ expected `}` in format string
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: 4 positional arguments in format string, but there are 3 arguments
+  --> $DIR/ifmt-bad-arg.rs:78:15
+   |
+LL |     println!("{} {:.*} {}", 1, 3.2, 4);
+   |               ^^ ^^--^ ^^   -  ---  -
+   |                    |           |
+   |                    |           this parameter corresponds to the precision flag
+   |                    this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
+   |
+   = note: positional arguments are zero-based
+   = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
+
+error: 4 positional arguments in format string, but there are 3 arguments
+  --> $DIR/ifmt-bad-arg.rs:81:15
+   |
+LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
+   |               ^^ ^^^----^ ^^   -  ---  -
+   |                     | |           |
+   |                     | |           this parameter corresponds to the precision flag
+   |                     | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
+   |                     this width flag expects an `usize` argument at position 7, but there are 3 arguments
+   |
+   = note: positional arguments are zero-based
+   = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
+
+error: invalid reference to positional argument 7 (there are 3 arguments)
+  --> $DIR/ifmt-bad-arg.rs:84:18
+   |
+LL |     println!("{} {:07$} {}", 1, 3.2, 4);
+   |                  ^^^--^
+   |                     |
+   |                     this width flag expects an `usize` argument at position 7, but there are 3 arguments
+   |
+   = note: positional arguments are zero-based
+   = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
+
+error: unknown format trait `foo`
+  --> $DIR/ifmt-bad-arg.rs:86:17
+   |
+LL |     println!("{:foo}", 1);
+   |                 ^^^
+   |
+   = note: the only appropriate formatting traits are:
+           - ``, which uses the `Display` trait
+           - `?`, which uses the `Debug` trait
+           - `e`, which uses the `LowerExp` trait
+           - `E`, which uses the `UpperExp` trait
+           - `o`, which uses the `Octal` trait
+           - `p`, which uses the `Pointer` trait
+           - `b`, which uses the `Binary` trait
+           - `x`, which uses the `LowerHex` trait
+           - `X`, which uses the `UpperHex` trait
+
+error: invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument)
+  --> $DIR/ifmt-bad-arg.rs:87:15
+   |
+LL |     println!("{5} {:4$} {6:7$}", 1);
+   |               ^^^ ^^--^ ^^^--^
+   |                     |      |
+   |                     |      this width flag expects an `usize` argument at position 7, but there is 1 argument
+   |                     this width flag expects an `usize` argument at position 4, but there is 1 argument
+   |
+   = note: positional arguments are zero-based
+   = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
+
+error: 2 positional arguments in format string, but no arguments were given
+  --> $DIR/ifmt-bad-arg.rs:92:15
+   |
+LL |     println!("{:.*}");
+   |               ^^--^
+   |                 |
+   |                 this precision flag adds an extra required argument at position 0, which is why there are 2 arguments expected
+   |
+   = note: positional arguments are zero-based
+   = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
+
+error[E0308]: mismatched types
+  --> $DIR/ifmt-bad-arg.rs:78:32
+   |
+LL |     println!("{} {:.*} {}", 1, 3.2, 4);
+   |                                ^^^ expected `usize`, found floating-point number
+   |
+   = note: expected reference `&usize`
+              found reference `&{float}`
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/ifmt-bad-arg.rs:81:35
+   |
+LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
+   |                                   ^^^ expected `usize`, found floating-point number
+   |
+   = note: expected reference `&usize`
+              found reference `&{float}`
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 36 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/expr/if/ifmt-bad-format-args.rs b/src/test/ui/expr/if/ifmt-bad-format-args.rs
new file mode 100644
index 00000000000..ba7301561bd
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-bad-format-args.rs
@@ -0,0 +1,4 @@
+fn main() {
+    format_args!(); //~ ERROR: requires at least a format string argument
+    format_args!(|| {}); //~ ERROR: must be a string literal
+}
diff --git a/src/test/ui/expr/if/ifmt-bad-format-args.stderr b/src/test/ui/expr/if/ifmt-bad-format-args.stderr
new file mode 100644
index 00000000000..8bb0d40629f
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-bad-format-args.stderr
@@ -0,0 +1,21 @@
+error: requires at least a format string argument
+  --> $DIR/ifmt-bad-format-args.rs:2:5
+   |
+LL |     format_args!();
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: format argument must be a string literal
+  --> $DIR/ifmt-bad-format-args.rs:3:18
+   |
+LL |     format_args!(|| {});
+   |                  ^^^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     format_args!("{}", || {});
+   |                  ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/expr/if/ifmt-unimpl.rs b/src/test/ui/expr/if/ifmt-unimpl.rs
new file mode 100644
index 00000000000..258f4eea509
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-unimpl.rs
@@ -0,0 +1,4 @@
+fn main() {
+    format!("{:X}", "3");
+    //~^ ERROR: `str: UpperHex` is not satisfied
+}
diff --git a/src/test/ui/expr/if/ifmt-unimpl.stderr b/src/test/ui/expr/if/ifmt-unimpl.stderr
new file mode 100644
index 00000000000..65b0f4a09b3
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-unimpl.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the trait bound `str: UpperHex` is not satisfied
+  --> $DIR/ifmt-unimpl.rs:2:21
+   |
+LL |     format!("{:X}", "3");
+   |                     ^^^ the trait `UpperHex` is not implemented for `str`
+   |
+   = note: required because of the requirements on the impl of `UpperHex` for `&str`
+   = note: required by `std::fmt::UpperHex::fmt`
+   = note: this error originates in a macro (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 E0277`.
diff --git a/src/test/ui/expr/if/ifmt-unknown-trait.rs b/src/test/ui/expr/if/ifmt-unknown-trait.rs
new file mode 100644
index 00000000000..158152c89a4
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-unknown-trait.rs
@@ -0,0 +1,4 @@
+fn main() {
+    format!("{:notimplemented}", "3");
+    //~^ ERROR: unknown format trait `notimplemented`
+}
diff --git a/src/test/ui/expr/if/ifmt-unknown-trait.stderr b/src/test/ui/expr/if/ifmt-unknown-trait.stderr
new file mode 100644
index 00000000000..459432bf4e4
--- /dev/null
+++ b/src/test/ui/expr/if/ifmt-unknown-trait.stderr
@@ -0,0 +1,19 @@
+error: unknown format trait `notimplemented`
+  --> $DIR/ifmt-unknown-trait.rs:2:16
+   |
+LL |     format!("{:notimplemented}", "3");
+   |                ^^^^^^^^^^^^^^
+   |
+   = note: the only appropriate formatting traits are:
+           - ``, which uses the `Display` trait
+           - `?`, which uses the `Debug` trait
+           - `e`, which uses the `LowerExp` trait
+           - `E`, which uses the `UpperExp` trait
+           - `o`, which uses the `Octal` trait
+           - `p`, which uses the `Pointer` trait
+           - `b`, which uses the `Binary` trait
+           - `x`, which uses the `LowerHex` trait
+           - `X`, which uses the `UpperHex` trait
+
+error: aborting due to previous error
+