--- /dev/null
+fn add(a: i32, b: i32) -> i32 {
+ a + b
+}
+fn main() {
+ // We shouldn't coerce capturing closure to a function
+ let cap = 0;
+ let _ = match "+" {
+ "+" => add,
+ "-" => |a, b| (a - b + cap) as i32,
+ _ => unimplemented!(),
+ };
+ //~^^^ ERROR `match` arms have incompatible types
+
+
+ // We shouldn't coerce capturing closure to a non-capturing closure
+ let _ = match "+" {
+ "+" => |a, b| (a + b) as i32,
+ "-" => |a, b| (a - b + cap) as i32,
+ _ => unimplemented!(),
+ };
+ //~^^^ ERROR `match` arms have incompatible types
+
+
+ // We shouldn't coerce non-capturing closure to a capturing closure
+ let _ = match "+" {
+ "+" => |a, b| (a + b + cap) as i32,
+ "-" => |a, b| (a - b) as i32,
+ _ => unimplemented!(),
+ };
+ //~^^^ ERROR `match` arms have incompatible types
+
+ // We shouldn't coerce capturing closure to a capturing closure
+ let _ = match "+" {
+ "+" => |a, b| (a + b + cap) as i32,
+ "-" => |a, b| (a - b + cap) as i32,
+ _ => unimplemented!(),
+ };
+ //~^^^ ERROR `match` arms have incompatible types
+}
--- /dev/null
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/closure_cap_coerce_many_fail.rs:9:16
+ |
+LL | let _ = match "+" {
+ | _____________-
+LL | | "+" => add,
+ | | --- this is found to be of type `fn(i32, i32) -> i32 {add}`
+LL | | "-" => |a, b| (a - b + cap) as i32,
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found closure
+LL | | _ => unimplemented!(),
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected type `fn(i32, i32) -> i32 {add}`
+ found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:9:16: 9:43 cap:_]`
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/closure_cap_coerce_many_fail.rs:18:16
+ |
+LL | let _ = match "+" {
+ | _____________-
+LL | | "+" => |a, b| (a + b) as i32,
+ | | --------------------- this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:37]`
+LL | | "-" => |a, b| (a - b + cap) as i32,
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
+LL | | _ => unimplemented!(),
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:37]`
+ found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:18:16: 18:43 cap:_]`
+ = note: no two closures, even if identical, have the same type
+ = help: consider boxing your closure and/or using it as a trait object
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/closure_cap_coerce_many_fail.rs:27:16
+ |
+LL | let _ = match "+" {
+ | _____________-
+LL | | "+" => |a, b| (a + b + cap) as i32,
+ | | --------------------------- this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:43 cap:_]`
+LL | | "-" => |a, b| (a - b) as i32,
+ | | ^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
+LL | | _ => unimplemented!(),
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:43 cap:_]`
+ found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:27:16: 27:37]`
+ = note: no two closures, even if identical, have the same type
+ = help: consider boxing your closure and/or using it as a trait object
+
+error[E0308]: `match` arms have incompatible types
+ --> $DIR/closure_cap_coerce_many_fail.rs:35:16
+ |
+LL | let _ = match "+" {
+ | _____________-
+LL | | "+" => |a, b| (a + b + cap) as i32,
+ | | --------------------------- this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:43 cap:_]`
+LL | | "-" => |a, b| (a - b + cap) as i32,
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
+LL | | _ => unimplemented!(),
+LL | | };
+ | |_____- `match` arms have incompatible types
+ |
+ = note: expected type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:43 cap:_]`
+ found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:35:16: 35:43 cap:_]`
+ = note: no two closures, even if identical, have the same type
+ = help: consider boxing your closure and/or using it as a trait object
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// check-pass
+// Ensure non-capturing Closure passes CoerceMany.
+fn foo(x: usize) -> usize {
+ 0
+}
+
+fn bar(x: usize) -> usize {
+ 1
+}
+
+fn main() {
+ // One FnDef and one non-capturing Closure
+ let _ = match 0 {
+ 0 => foo,
+ 2 => |a| 2,
+ _ => unimplemented!(),
+ };
+
+ let _ = match 0 {
+ 2 => |a| 2,
+ 0 => foo,
+ _ => unimplemented!(),
+ };
+
+ let _ = [foo, |a| 2];
+ let _ = [|a| 2, foo];
+
+
+
+ // Two FnDefs and one non-capturing Closure
+ let _ = match 0 {
+ 0 => foo,
+ 1 => bar,
+ 2 => |a| 2,
+ _ => unimplemented!(),
+ };
+
+ let _ = match 0 {
+ 0 => foo,
+ 2 => |a| 2,
+ 1 => bar,
+ _ => unimplemented!(),
+ };
+
+ let _ = match 0 {
+ 2 => |a| 2,
+ 0 => foo,
+ 1 => bar,
+ _ => unimplemented!(),
+ };
+
+ let _ = [foo, bar, |a| 2];
+ let _ = [foo, |a| 2, bar];
+ let _ = [|a| 2, foo, bar];
+
+
+
+ // One FnDef and two non-capturing Closures
+ let _ = match 0 {
+ 0 => foo,
+ 1 => |a| 1,
+ 2 => |a| 2,
+ _ => unimplemented!(),
+ };
+
+ let _ = match 0 {
+ 1 => |a| 1,
+ 0 => foo,
+ 2 => |a| 2,
+ _ => unimplemented!(),
+ };
+
+ let _ = match 0 {
+ 1 => |a| 1,
+ 2 => |a| 2,
+ 0 => foo,
+ _ => unimplemented!(),
+ };
+
+ let _ = [foo, |a| 1, |a| 2];
+ let _ = [|a| 1, foo, |a| 2];
+ let _ = [|a| 1, |a| 2, foo];
+
+
+
+ // Three non-capturing Closures
+ let _ = match 0 {
+ 0 => |a: usize| 0,
+ 1 => |a| 1,
+ 2 => |a| 2,
+ _ => unimplemented!(),
+ };
+
+ let _ = [|a: usize| 0, |a| 1, |a| 2];
+
+
+
+ // Three non-capturing Closures variable
+ let clo0 = |a: usize| 0;
+ let clo1 = |a| 1;
+ let clo2 = |a| 2;
+ let _ = match 0 {
+ 0 => clo0,
+ 1 => clo1,
+ 2 => clo2,
+ _ => unimplemented!(),
+ };
+
+ let clo0 = |a: usize| 0;
+ let clo1 = |a| 1;
+ let clo2 = |a| 2;
+ let _ = [clo0, clo1, clo2];
+
+
+
+ // --- Function pointer related part
+
+ // Closure is not in a variable
+ type FnPointer = fn(usize) -> usize;
+
+ let _ = match 0 {
+ 0 => foo as FnPointer,
+ 2 => |a| 2,
+ _ => unimplemented!(),
+ };
+ let _ = match 0 {
+ 2 => |a| 2,
+ 0 => foo as FnPointer,
+ _ => unimplemented!(),
+ };
+ let _ = [foo as FnPointer, |a| 2];
+ let _ = [|a| 2, foo as FnPointer];
+ let _ = [foo, bar, |x| x];
+ let _ = [foo as FnPointer, bar, |x| x];
+ let _ = [foo, bar as FnPointer, |x| x];
+ let _ = [foo, bar, (|x| x) as FnPointer];
+ let _ = [foo as FnPointer, bar as FnPointer, |x| x];
+
+ // Closure is in a variable
+ let x = |a| 2;
+ let _ = match 0 {
+ 0 => foo as FnPointer,
+ 2 => x,
+ _ => unimplemented!(),
+ };
+ let x = |a| 2;
+ let _ = match 0 {
+ 2 => x,
+ 0 => foo as FnPointer,
+ _ => unimplemented!(),
+ };
+ let x = |a| 2;
+ let _ = [foo as FnPointer, x];
+ let _ = [x, foo as FnPointer];
+
+ let x = |a| 2;
+ let _ = [foo, bar, x];
+ let x: FnPointer = |a| 2;
+ let _ = [foo, bar, x];
+ let x = |a| 2;
+ let _ = [foo, bar as FnPointer, x];
+ let x = |a| 2;
+ let _ = [foo as FnPointer, bar, x];
+ let x = |a| 2;
+ let _ = [foo as FnPointer, bar as FnPointer, x];
+}
--- /dev/null
+// run-pass
+// Ensure non-capturing Closure passing CoerceMany work correctly.
+fn foo(_: usize) -> usize {
+ 0
+}
+
+fn bar(_: usize) -> usize {
+ 1
+}
+
+fn add(a: i32, b: i32) -> i32 {
+ a + b
+}
+
+fn main() {
+ // Coerce result check
+
+ type FnPointer = fn(usize) -> usize;
+
+ let c = |x| x;
+ let c_pointer: FnPointer = c;
+ assert_eq!(c_pointer(42), 42);
+
+ let f = match 0 {
+ 0 => foo,
+ 1 => |_| 1,
+ _ => unimplemented!(),
+ };
+ assert_eq!(f(42), 0);
+
+ let f = match 2 {
+ 2 => |_| 2,
+ 0 => foo,
+ _ => unimplemented!(),
+ };
+ assert_eq!(f(42), 2);
+
+ let f = match 1 {
+ 0 => foo,
+ 1 => bar,
+ 2 => |_| 2,
+ _ => unimplemented!(),
+ };
+ assert_eq!(f(42), 1);
+
+ let clo0 = |_: usize| 0;
+ let clo1 = |_| 1;
+ let clo2 = |_| 2;
+ let f = match 0 {
+ 0 => clo0,
+ 1 => clo1,
+ 2 => clo2,
+ _ => unimplemented!(),
+ };
+ assert_eq!(f(42), 0);
+
+ let funcs = [add, |a, b| (a - b) as i32];
+ assert_eq!([funcs[0](5, 5), funcs[1](5, 5)], [10, 0]);
+}
--- /dev/null
+// Ensure we get unsafe function after coercion
+unsafe fn add(a: i32, b: i32) -> i32 {
+ a + b
+}
+fn main() {
+ // We can coerce non-capturing closure to unsafe function
+ let foo = match "+" {
+ "+" => add,
+ "-" => |a, b| (a - b) as i32,
+ _ => unimplemented!(),
+ };
+ let result: i32 = foo(5, 5); //~ ERROR call to unsafe function
+
+
+ // We can coerce unsafe function to non-capturing closure
+ let foo = match "+" {
+ "-" => |a, b| (a - b) as i32,
+ "+" => add,
+ _ => unimplemented!(),
+ };
+ let result: i32 = foo(5, 5); //~ ERROR call to unsafe function
+}
--- /dev/null
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:12:23
+ |
+LL | let result: i32 = foo(5, 5);
+ | ^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:21:23
+ |
+LL | let result: i32 = foo(5, 5);
+ | ^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+// run-pass
+// Ensure we get correct unsafe function after coercion
+unsafe fn add(a: i32, b: i32) -> i32 {
+ a + b
+}
+fn main() {
+ // We can coerce non-capturing closure to unsafe function
+ let foo = match "+" {
+ "+" => add,
+ "-" => |a, b| (a - b) as i32,
+ _ => unimplemented!(),
+ };
+ assert_eq!(unsafe { foo(5, 5) }, 10);
+
+
+ // We can coerce unsafe function to non-capturing closure
+ let foo = match "-" {
+ "-" => |a, b| (a - b) as i32,
+ "+" => add,
+ _ => unimplemented!(),
+ };
+ assert_eq!(unsafe { foo(5, 5) }, 0);
+}
--- /dev/null
+// check-pass
+fn main() {
+ let _: i32 = (match "" {
+ "+" => ::std::ops::Add::add,
+ "-" => ::std::ops::Sub::sub,
+ "<" => |a,b| (a < b) as i32,
+ _ => unimplemented!(),
+ })(5, 5);
+}
--- /dev/null
+// check-pass
+fn useful(i: usize) -> usize {
+ i
+}
+
+fn useful2(i: usize) -> usize {
+ i
+}
+
+fn main() {
+ for f in &[useful, useful2, |x| x] {
+ println!("{}", f(6));
+ }
+}
2 => |c| c - 1,
_ => |c| c - 1
};
- //~^^^ ERROR `match` arms have incompatible types
+ //~^^^^ ERROR type annotations needed
}
fn main() { }
= note: no two closures, even if identical, have the same type
= help: consider boxing your closure and/or using it as a trait object
-error[E0308]: `match` arms have incompatible types
- --> $DIR/issue-24036.rs:10:14
+error[E0282]: type annotations needed
+ --> $DIR/issue-24036.rs:9:15
|
-LL | let x = match 1usize {
- | _____________-
-LL | | 1 => |c| c + 1,
- | | --------- this is found to be of type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
-LL | | 2 => |c| c - 1,
- | | ^^^^^^^^^ expected closure, found a different closure
-LL | | _ => |c| c - 1
-LL | | };
- | |_____- `match` arms have incompatible types
- |
- = note: expected type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
- found closure `[closure@$DIR/issue-24036.rs:10:14: 10:23]`
- = note: no two closures, even if identical, have the same type
- = help: consider boxing your closure and/or using it as a trait object
+LL | 1 => |c| c + 1,
+ | ^ consider giving this closure parameter a type
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0282, E0308.
+For more information about an error, try `rustc --explain E0282`.