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

Higher-ranked fn pointers can be cast but no longer coerce #95132

Closed
QuineDot opened this issue Mar 20, 2022 · 4 comments
Closed

Higher-ranked fn pointers can be cast but no longer coerce #95132

QuineDot opened this issue Mar 20, 2022 · 4 comments
Labels
C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another.

Comments

@QuineDot
Copy link

Code

I tried this code:

fn f<'long: 'short, 'short>(_: &'short &'long ()) {
    let higher_ranked: for<'any> fn(&'any ()) = |_| {};
    let long: fn(&'long ()) = |_| {};
    let short: fn(&'short()) = |_| {};
    let stat: fn(&'static ()) = |_| {};

    // Contravariance: `fn(&'short ())` is a subtype of `fn(&'long ())`, etc.
    let _: fn(&'static ()) = long;
    let _: fn(&'long ()) = short;

    // The higher-ranked type is a subtype of all of them
    let _: fn(&'static ()) = higher_ranked;
    let _: fn(&'long ()) = higher_ranked;
    let _: fn(&'short ()) = higher_ranked;
}

I expected to see this happen: Successful compilation

Instead, this happened: Compiler error:


error[E0308]: mismatched types
  --> <source>:12:12
   |
12 |     let _: fn(&'static ()) = higher_ranked;
   |            ^^^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected fn pointer `fn(&'static ())`
              found fn pointer `for<'any> fn(&'any ())`

error[E0308]: mismatched types
  --> <source>:13:12
   |
13 |     let _: fn(&'long ()) = higher_ranked;
   |            ^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected fn pointer `fn(&'long ())`
              found fn pointer `for<'any> fn(&'any ())`

error[E0308]: mismatched types
  --> <source>:14:12
   |
14 |     let _: fn(&'short ()) = higher_ranked;
   |            ^^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected fn pointer `fn(&'short ())`
              found fn pointer `for<'any> fn(&'any ())`

Version it worked on

It most recently worked on: Rust 1.35.

It works on every version before that which I spot checked (but I did not spot check all of them).

Versions before 1.18.0 cannot coerce a closure to a function pointer, but this variation:

fn g(_: &()) {}
fn f<'long: 'short, 'short>(_: &'short &'long ()) {
    let higher_ranked: for<'any> fn(&'any ()) = g;

    // The higher-ranked type is a subtype of all of them
    let _: fn(&'static ()) = higher_ranked;
    let _: fn(&'long ()) = higher_ranked;
    let _: fn(&'short ()) = higher_ranked;
}

Works all the way back to Rust 1.0.0.

Versions with regression

Rust 1.36.0 and all those which I spot-checked after this version.

The error changes in Rust 1.56.0 due to one of the #57374 fixes; I didn't track down which.

Current playground, any version.

  • Stable version: 1.59.0
  • Beta version: 1.60.0-beta.5 (2022-03-18 6ee5a40)
  • Nightly version: 1.61.0-nightly (2022-03-18 1bfe40d)

Workaround

Casting still works:

    let _: fn(&'static ()) = higher_ranked as _;
    let _: fn(&'long ()) = higher_ranked as _;
    let _: fn(&'short ()) = higher_ranked as _;

But RFC 401 says this should not be necessary.

@rustbot modify labels: +regression-from-stable-to-stable -regression-untriaged

@QuineDot QuineDot added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Mar 20, 2022
@rustbot rustbot added I-prioritize Issue: Indicates that prioritization has been requested for this issue. regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed regression-untriaged Untriaged performance or correctness regression. labels Mar 20, 2022
@lcnr
Copy link
Contributor

lcnr commented Mar 21, 2022

this broke with the introduction of nll in the 2015 edition, see https://rust.godbolt.org/z/3sr77dP6z, and is caused by UserTypeAnnotations being broken in mir. Already working on fixing this, cc #93856

@apiraino
Copy link
Contributor

Assigning priority as discussed in the Zulip thread of the Prioritization Working Group.

@rustbot label -I-prioritize +P-medium

@rustbot rustbot added P-medium Medium priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Mar 21, 2022
@Jules-Bertholet
Copy link
Contributor

Jules-Bertholet commented Nov 8, 2022

The example code now compiles successfully—fixed by #96515, I think.

I believe this issue can be closed.

@lcnr
Copy link
Contributor

lcnr commented Nov 8, 2022

already added tests for this issue in #96515. Closing

@lcnr lcnr closed this as completed Nov 8, 2022
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. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another.
Projects
None yet
Development

No branches or pull requests

5 participants