Skip to content

Closures of different types that do not capture the environment are automatically coerced to function pointers #86885

Open
@shepmaster

Description

@shepmaster

I tried this code:

fn returns_closure(maybe: bool) -> impl Fn(i32) -> i32 {
    if maybe {
        |x| x + 1
    } else {
        |y| y + 2
    }
}

I expected that the compilation would fail because the closures have different types:

error[E0308]: `if` and `else` have incompatible types
 --> src/main.rs:5:9
  |
2 | /     if maybe {
3 | |         |x| x + 1
  | |         --------- expected because of this
4 | |     } else {
5 | |         |y| y + 2
  | |         ^^^^^^^^^ expected closure, found a different closure
6 | |     }
  | |_____- `if` and `else` have incompatible types
  |
  = note: expected type `[closure@src/main.rs:3:9: 3:18]`
          found closure `[closure@src/main.rs:5:9: 5:18]`

Instead, the code compiles.

Meta

Fails to compile (as expected)

rustc +1.44 --version --verbose:

rustc 1.44.1 (c7087fe00 2020-06-17)
binary: rustc
commit-hash: c7087fe00d2ba919df1d813c040a5d47e43b0fe7
commit-date: 2020-06-17
host: x86_64-apple-darwin
release: 1.44.1
LLVM version: 9.0

Compiles (unexpectedly)

rustc +1.45 --version --verbose:

rustc 1.45.2 (d3fb005a3 2020-07-31)
binary: rustc
commit-hash: d3fb005a39e62501b8b0b356166e515ae24e2e54
commit-date: 2020-07-31
host: x86_64-apple-darwin
release: 1.45.2
LLVM version: 10.0

rustc +stable --version --verbose

rustc 1.53.0 (53cb7b09b 2021-06-17)
binary: rustc
commit-hash: 53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b
commit-date: 2021-06-17
host: x86_64-apple-darwin
release: 1.53.0
LLVM version: 12.0.1

rustc +nightly --version --verbose

rustc 1.55.0-nightly (7c3872e6b 2021-06-24)
binary: rustc
commit-hash: 7c3872e6bfd555d2ad753ac1f871db3bd7f2a547
commit-date: 2021-06-24
host: x86_64-apple-darwin
release: 1.55.0-nightly
LLVM version: 12.0.1

Activity

added
T-langRelevant to the language team
C-bugCategory: This is a bug.
on Jul 5, 2021
shepmaster

shepmaster commented on Jul 5, 2021

@shepmaster
MemberAuthor

Looking at the MIR, I see this:

fn returns_closure(_1: bool) -> fn(i32) -> i32 {

I am surprised that the compiler automatically converted my code into dynamic dispatch.

shepmaster

shepmaster commented on Jul 5, 2021

@shepmaster
MemberAuthor

Friends have pointed me towards #71599 as the causal root.

danielhenrymantilla

danielhenrymantilla commented on Jul 6, 2021

@danielhenrymantilla
Contributor

What about designing an allow-by-default lint triggering on such coercions? implicit_dyn_dispatch_coercion or something along those lines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @shepmaster@danielhenrymantilla

        Issue actions

          Closures of different types that do not capture the environment are automatically coerced to function pointers · Issue #86885 · rust-lang/rust