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

RPITIT causes incorrect "dropped while still borrowed" error in some cases #131490

Open
cdhowie opened this issue Oct 10, 2024 · 4 comments
Open
Labels
C-bug Category: This is a bug. F-return_position_impl_trait_in_trait `#![feature(return_position_impl_trait_in_trait)]` needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.

Comments

@cdhowie
Copy link

cdhowie commented Oct 10, 2024

From this SO question, the following code does not compile:

trait Iterable {
    fn owned_iter(&self) -> impl Iterator<Item = usize> + 'static;
}

struct B<T> {
    x: T,
}

impl<T: Iterable + Clone> Iterable for B<T> {
    fn owned_iter(&self) -> impl Iterator<Item = usize> + 'static {
        let y = self.x.clone();
        y.owned_iter() // error[E0597]: `y` does not live long enough
    }
}

However, boxing the iterator as a trait object allows it to compile:

trait Iterable {
    fn owned_iter(&self) -> impl Iterator<Item = usize> + 'static;
}

struct B<T> {
    x: T,
}

impl<T: Iterable + Clone> Iterable for B<T> {
    fn owned_iter(&self) -> impl Iterator<Item = usize> + 'static {
        let y = self.x.clone();
        let b: Box<dyn Iterator<Item = usize>> = Box::new(y.owned_iter());
        b
    }
}

Notably, not cloning self.x and simply returning self.x.owned_iter() also works.

I don't see any reason why the first code block shouldn't compile, especially while the boxed version and the non-cloning version do.

Meta

rustc --version --verbose:

rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7

It also fails to compile on 1.83.0-nightly (2024-10-09 eb4e234).

@cdhowie cdhowie added the C-bug Category: This is a bug. label Oct 10, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 10, 2024
@compiler-errors
Copy link
Member

This was fixed by #116040, but that was not sound. Fixing this is particularly nontrivial.

This may be easier to address soon if #131033 lands and is then stabilized, since you should be able to express the +'static as +use<Self> instead.

@cdhowie
Copy link
Author

cdhowie commented Oct 10, 2024

But the returned iterator in this case doesn't even borrow self, so it doesn't seem like that should be necessary. It also changes the semantic meaning of the returned type to borrow self when the intent of this code is exactly the opposite. Am I missing something?

@compiler-errors
Copy link
Member

Am I missing something?

I think so :)

So the RPITIT wouldn't be capturing self: &Self, but instead it would be capturing Self, the implicit type parameter of the trait. That is to say, he capture we want to avoid is the elided lifetime 'a (which is elided in this case) like:

trait Iterable {
    fn owned_iter<'a>(&'a self) -> impl Iterator<Item = usize> + 'static;
}

@lqd
Copy link
Member

lqd commented Oct 11, 2024

Since #131033 landed, this should work on nightly now

#![feature(precise_capturing_in_traits)]

trait Iterable {
    fn owned_iter(&self) -> impl Iterator<Item = usize> + use<Self>;
}

struct B<T> {
    x: T,
}

impl<T: Iterable + Clone> Iterable for B<T> {
    fn owned_iter(&self) -> impl Iterator<Item = usize> + use<T> {
        let y = self.x.clone();
        y.owned_iter()
    }
}

@lolbinarycat lolbinarycat added the F-return_position_impl_trait_in_trait `#![feature(return_position_impl_trait_in_trait)]` label Oct 17, 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. F-return_position_impl_trait_in_trait `#![feature(return_position_impl_trait_in_trait)]` needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.
Projects
None yet
Development

No branches or pull requests

5 participants