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

Regression in required trait bounds in Rust 1.78.0 #124984

Closed
alexcrichton opened this issue May 10, 2024 · 9 comments
Closed

Regression in required trait bounds in Rust 1.78.0 #124984

alexcrichton opened this issue May 10, 2024 · 9 comments
Labels
C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression.

Comments

@alexcrichton
Copy link
Member

alexcrichton commented May 10, 2024

Code

This code

pub trait Host {}

impl<T: ?Sized   Host> Host for &mut T {}

pub trait GetHost<T>: Send   Sync   Copy   'static {
    fn get_host<'a>(&self, data: &'a mut T) -> impl Host;
}

impl<T, U, F> GetHost<T> for F
where
    U: Host,
    F: Fn(&mut T) -> &mut U   Send   Sync   Copy   'static,
{
    fn get_host<'a>(&self, data: &'a mut T) -> impl Host {
        self(data)
    }
}

fn main() {}

Compiles successfully with Rust 1.77.0 but fails to compile with Rust 1.78.0:

error[E0309]: the parameter type `U` may not live long enough
  --> foo.rs:15:9
   |
14 |     fn get_host<'a>(&self, data: &'a mut T) -> impl Host {
   |                 -- the parameter type `U` must be valid for the lifetime `'a` as defined here...
15 |         self(data)
   |         ^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
14 |     fn get_host<'a>(&self, data: &'a mut T) -> impl Host where U: 'a {
   |                                                                     

error: aborting due to 1 previous error

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

Version it worked on

It most recently worked on: 1.77.0

Version with regression

rustc --version --verbose:

rustc 1.78.0 (9b00956e5 2024-04-29)
binary: rustc
commit-hash: 9b00956e56009bab2aa15d7bff10916599e3d6d6
commit-date: 2024-04-29
host: x86_64-unknown-linux-gnu
release: 1.78.0
LLVM version: 18.1.2

Information from cargo bisect-rustc

Regression in rust-lang-ci@68a543d (#118882)

searched nightlies: from nightly-2024-02-01 to nightly-2024-03-16
regressed nightly: nightly-2024-02-15
searched commit range: a84bb95...ee9c7c9
regressed commit: 7508c3e

bisected with cargo-bisect-rustc v0.6.8

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --start 1.77.0 --end 1.78.0 --script rustc --preserve -- foo.rs --crate-type lib
@alexcrichton alexcrichton added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels May 10, 2024
@rustbot rustbot added I-prioritize Issue: Indicates that prioritization has been requested for this issue. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels May 10, 2024
@lcnr
Copy link
Contributor

lcnr commented May 10, 2024

your code snippet does not seem to compile in 1.77 or 1.76? 🤔 https://rust.godbolt.org/z/vzhn87bfz

@alexcrichton
Copy link
Member Author

That may be a godbolt issue perhaps? https://rust.godbolt.org/z/e6nxK5oaq shows it passing with 77/76 and locally 1.77.0 compiles the example for me.

@compiler-errors
Copy link
Member

compiler-errors commented May 10, 2024

@alexcrichton: The code you shared in the issue has an extra 'a, causing it to fail both before and after 1.78.

@alexcrichton
Copy link
Member Author

Er apologies, that's my mistake. I was trying various versions locally and got the wires crossed. I've updated the above which also explains why the two godbolt links are differing in results.

I was surprised that this actually worked on 1.77.0, so is this actually a soundness issue fixed by #118882?

@lcnr
Copy link
Contributor

lcnr commented May 10, 2024

The hidden type of impl Host ends up as &'a U and we currently don't have an implied U: 'a bound here. This breaks the invariants of our type system, using a pattern which can result in actual unsoundnesses. I don't think your snippet is unsound as is, but also don't know how we would fix #114936 without breaking your example

@alexcrichton
Copy link
Member Author

Ah ok, if this is expected no worries, I just wanted to confirm!

Would you happen to know off the top of your head if there's a way we could somehow get this working? The ideal thing we want is:

fn foo<T>(f: impl Fn(&mut T) -> impl Host) { ... }

and we're trying to hack around it of sorts with a custom GetHost trait, but I'm having a tough time figuring out how to model this use case.

@alexcrichton
Copy link
Member Author

Ah well in any case this appears to be expected so there's no issue here I believe. We'll work on getting something alternative working instead.

@lcnr
Copy link
Contributor

lcnr commented May 10, 2024

Would you happen to know off the top of your head if there's a way we could somehow get this working? The ideal thing we want is:

It's really hard as you need a for<'a> U: 'a bound which currently forces U to be 'static while ideally it would only allow instantiating 'a with lifetimes which outlive 'a. We will support this in a few years as these kinds of bounds are necessary to fix e.g. #25860

but up until then I also don't have a nice fix for this :/

@alexcrichton
Copy link
Member Author

Ah no worries! I was able to adapt this and get something working, albeit not as egonomically as desired.

In any case thanks for the quick responses here, it's definitely appreciated!

@jieyouxu jieyouxu removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 10, 2024
@apiraino apiraino removed the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label May 11, 2024
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. regression-untriaged Untriaged performance or correctness regression.
Projects
None yet
Development

No branches or pull requests

6 participants