-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test for coercion between (FnDef | Closure) and (FnDef | Closure)
- Loading branch information
Showing
11 changed files
with
431 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 changes: 166 additions & 0 deletions
166
src/test/ui/closures/closure_no_cap_coerce_many_check_pass.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 changes: 59 additions & 0 deletions
59
src/test/ui/closures/closure_no_cap_coerce_many_run_pass.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 changes: 22 additions & 0 deletions
22
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
19 changes: 19 additions & 0 deletions
19
src/test/ui/closures/closure_no_cap_coerce_many_unsafe_0.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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`. |
Oops, something went wrong.