Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile error with type mismatch in Fn() -> ! #129441

Closed
Seidko opened this issue Aug 23, 2024 · 4 comments
Closed

Compile error with type mismatch in Fn() -> ! #129441

Seidko opened this issue Aug 23, 2024 · 4 comments
Labels
F-never_type `#![feature(never_type)]`

Comments

@Seidko
Copy link

Seidko commented Aug 23, 2024

I tried this code:

#![feature(never_type)]

fn main(){
    let vec = vec!["0"];
    let closure = || -> ! {
        dbg!(vec);
        panic!()
    };
    let s = vec.get(0).unwrap_or_else(closure);
}

playground link

I expected these code to compile.

Instead, I got type can not assign:

error[E0271]: expected `{[email protected]:5:19}` to be a closure that returns `&&str`, but it returns `!`
    --> src/main.rs:9:39
     |
9    |     let s = vec.get(0).unwrap_or_else(closure);
     |                        -------------- ^^^^^^^ expected `&&str`, found `!`
     |                        |
     |                        required by a bound introduced by this call
     |
     = note: expected reference `&&str`
                     found type `!`
note: required by a bound in `Option::<T>::unwrap_or_else`
    --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1006:24
     |
1004 |     pub fn unwrap_or_else<F>(self, f: F) -> T
     |            -------------- required by a bound in this associated function
1005 |     where
1006 |         F: FnOnce() -> T,
     |                        ^ required by this bound in `Option::<T>::unwrap_or_else`

For more information about this error, try `rustc --explain E0271`.

The closure never return and we no need to care about it return and rust's never type can be assigned to any type in type theory.

Meta

rustc --version --verbose:

rustc 1.82.0-nightly (a32d4a0e8 2024-08-21)
binary: rustc
commit-hash: a32d4a0e822a29a6682e08b75a8df4c29c7fa9f1
commit-date: 2024-08-21
host: x86_64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 19.1.0

There are no backtrace output with RUST_BACKTRACE=1

Tracking:

@Seidko Seidko added the C-bug Category: This is a bug. label Aug 23, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Aug 23, 2024
@theemathas
Copy link
Contributor

This is expected behavior. The type ! is automatically convertable to &&str. However, a Fn() -> ! closure is not automatically convertable to a Fn() -> &&str closure. Creating a new closure (and fixing the ownership issue) causes the code to compile:

#![feature(never_type)]

fn main(){
    let vec = vec!["0"];
    let closure = || -> ! {
        dbg!(&vec);
        panic!()
    };
    let s = vec.get(0).unwrap_or_else(|| closure());
}

Here, the || closure() implicitly converts the return value of closure() from type ! to type &&str. (Conceptually, it's like || convert_never_to_str(closure()).

@Seidko
Copy link
Author

Seidko commented Aug 23, 2024

@theemathas I see, but I don't understand why the closure type can't be converted automatically, why is that?

@traviscross traviscross added the F-never_type `#![feature(never_type)]` label Aug 23, 2024
@traviscross
Copy link
Contributor

@rustbot labels -C-bug

I see, but I don't understand why the closure type can't be converted automatically, why is that?

It's just not how Rust works today. Maybe it could someday. Someone would need to write up an RFC motivating it and working through all the many details and implications of it.

@traviscross traviscross closed this as not planned Won't fix, can't repro, duplicate, stale Aug 23, 2024
@rustbot rustbot removed the C-bug Category: This is a bug. label Aug 23, 2024
@jieyouxu jieyouxu removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Aug 23, 2024
@thomaseizinger
Copy link
Contributor

@theemathas I see, but I don't understand why the closure type can't be converted automatically, why is that?

I think it is for the same reason that you can't pass a closure Fn() -> u32 where a Fn() -> u64 is expected: They are simply different types even if the return type could in theory be converted automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-never_type `#![feature(never_type)]`
Projects
None yet
Development

No branches or pull requests

6 participants