Skip to content

Type inference doesn't properly handle closures that don't return #111539

@zackw

Description

@zackw

In the code below, both of the demo_* functions provoke type inference errors that I believe should not happen.

use std::error::Error; use std::process::exit; fn demo_one<F>(f: F) -> () where F: FnOnce() -> Result<(), Box<dyn Error>>, { f().or_else(|e| { eprintln!("{:?}", e); exit(1) }); } fn demo_two<F>(f: F) -> () where F: FnOnce() -> Result<(), Box<dyn Error>>, { f().or_else(|e| -> ! { eprintln!("{:?}", e); exit(1) }); }

The errors I observe are (suggestions omitted for space):

error[E0282]: type annotations needed for `Result<(), F>` --> src/lib.rs:8:17 8 | f().or_else(|e| { error[E0271]]: expected `[closure@lib.rs:18:17]` to be a closure that returns `Result<(), _>`, but it returns `!` --> src/lib.rs:18:17 18 | f().or_else(|e| -> ! { 

I believe these errors to be incorrect, because:

  1. Both closures end with a call to std::process::exit, which does not return. The return type of the closure in demo_one should therefore have been inferred to be !, matching the closure in demo_two. (Note: whether that call has a ; afterward does not make any difference.)
  2. As documented in https://doc.rust-lang.org/std/primitive.never.html, ! coerces to any type, therefore a callable which never returns ought to be compatible with a caller expecting any return type.

Meta

rustc --version --verbose:

rustc 1.69.0 (84c898d65 2023-04-16) binary: rustc commit-hash: 84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc commit-date: 2023-04-16 host: aarch64-unknown-linux-gnu release: 1.69.0 LLVM version: 15.0.7 

Identical behavior observed from nightly (playground link).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-diagnosticsArea: Messages for errors, warnings, and lintsA-inferenceArea: Type inferenceC-bugCategory: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions