mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-03 12:13:43 +00:00
Test for coercion between (FnDef | Closure) and (FnDef | Closure)
This commit is contained in:
parent
59cc5b1ba3
commit
42396b1fac
39
src/test/ui/closures/closure_cap_coerce_many_fail.rs
Normal file
39
src/test/ui/closures/closure_cap_coerce_many_fail.rs
Normal file
@ -0,0 +1,39 @@
|
||||
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
|
||||
}
|
73
src/test/ui/closures/closure_cap_coerce_many_fail.stderr
Normal file
73
src/test/ui/closures/closure_cap_coerce_many_fail.stderr
Normal file
@ -0,0 +1,73 @@
|
||||
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`.
|
166
src/test/ui/closures/closure_no_cap_coerce_many_check_pass.rs
Normal file
166
src/test/ui/closures/closure_no_cap_coerce_many_check_pass.rs
Normal file
@ -0,0 +1,166 @@
|
||||
// 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];
|
||||
}
|
59
src/test/ui/closures/closure_no_cap_coerce_many_run_pass.rs
Normal file
59
src/test/ui/closures/closure_no_cap_coerce_many_run_pass.rs
Normal file
@ -0,0 +1,59 @@
|
||||
// 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]);
|
||||
}
|
22
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs
Normal file
22
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// 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
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
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`.
|
23
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs
Normal file
23
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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);
|
||||
}
|
9
src/test/ui/closures/issue-46742.rs
Normal file
9
src/test/ui/closures/issue-46742.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// check-pass
|
||||
fn main() {
|
||||
let _: i32 = (match "" {
|
||||
"+" => ::std::ops::Add::add,
|
||||
"-" => ::std::ops::Sub::sub,
|
||||
"<" => |a,b| (a < b) as i32,
|
||||
_ => unimplemented!(),
|
||||
})(5, 5);
|
||||
}
|
14
src/test/ui/closures/issue-48109.rs
Normal file
14
src/test/ui/closures/issue-48109.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// 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));
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ fn closure_from_match() {
|
||||
2 => |c| c - 1,
|
||||
_ => |c| c - 1
|
||||
};
|
||||
//~^^^ ERROR `match` arms have incompatible types
|
||||
//~^^^^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -11,24 +11,13 @@ LL | x = |c| c + 1;
|
||||
= 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`.
|
||||
|
Loading…
Reference in New Issue
Block a user