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

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

Open
shepmaster opened this issue Jul 5, 2021 · 3 comments
Labels
C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@shepmaster
Copy link
Member

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
@shepmaster shepmaster added T-lang Relevant to the language team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Jul 5, 2021
@shepmaster
Copy link
Member Author

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
Copy link
Member Author

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

@danielhenrymantilla
Copy link
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
Labels
C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

2 participants