Open
Description
I tried this code:
Version 1 (Compiles successfully):
use std::hint::black_box;
use std::any::type_name_of_val;
fn foo() {}
fn bar() {}
fn main() {
let x = if black_box(true) { foo } else { bar };
println!("{}", type_name_of_val(&x)); // observing `fn` items being cast to `fn` pointers, output: `fn()`
}
Version 2 (Fails to compile, tuple)
use std::hint::black_box;
use std::any::type_name_of_val;
fn foo() {}
fn bar() {}
fn main() {
let x = if black_box(true) { (foo,) } else { (bar,) }; // mismatched types, no casting observed
println!("{}", type_name_of_val(&x.0));
}
Version 3 (Fails to compile, struct)
use std::any::type_name_of_val;
use std::hint::black_box;
fn foo() {}
fn bar() {}
struct F<T>
where
T: Fn(),
{
inner: T,
}
fn main() {
let x = if black_box(true) {
F { inner: foo }
} else {
F { inner: bar }
}; // mismatched types, no casting observed
println!("{}", type_name_of_val(&x.inner));
}
I expected to see this happen:
In all versions, I expected the code to either compile successfully or fail with the same type mismatch error.
Instead, this happened:
Version 1 compiles successfully, while version 2 and version 3 fail with the same error expected fn item, found a different fn item
. Explicitly specifying the fn
pointer type for x
resolves the issue. By the way, the use of impl_trait_in_bindings
feature does not affect this behavior.
Meta
rustc --version --verbose
:
rustc 1.86.0-nightly (99768c80a 2025-01-23)
binary: rustc
commit-hash: 99768c80a1c094a5cfc3b25a04e7a99de7210eae
commit-date: 2025-01-23
host: x86_64-unknown-linux-gnu
release: 1.86.0-nightly
LLVM version: 19.1.7
RUST_BACKTRACE=1
doesn't provide additional information for any of the versions.
Version 1 only provides Finished ...
and no other information.
RUST_BACKTRACE=1
doesn't provide additional information for any of the versions.Finished ...
and no other information.
Version 2
Compiling rust-test v0.1.0 (.../rust-test)
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:8:50
|
8 | let x = if black_box(true) { (foo,) } else { (bar,) }; // mismatched types, no casting observed
| ------ ^^^^^^ expected `(fn() {foo},)`, found `(fn() {bar},)`
| |
| expected because of this
|
= note: expected tuple `(fn() {foo},)`
found tuple `(fn() {bar},)`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rust-test` (bin "rust-test") due to 1 previous error
Version 3
Compiling rust-test v0.1.0 (.../rust-test)
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:18:9
|
15 | let x = if black_box(true) {
| _____________-
16 | | F { inner: foo }
| | ---------------- expected because of this
17 | | } else {
18 | | F { inner: bar }
| | ^^^^^^^^^^^^^^^^ expected `F<fn() {foo}>`, found `F<fn() {bar}>`
19 | | }; // mismatched types, no casting observed
| |_____- `if` and `else` have incompatible types
|
= note: expected struct `F<fn() {foo}>`
found struct `F<fn() {bar}>`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rust-test` (bin "rust-test") due to 1 previous error