RPITIT with Send trait marker breaks borrow checker #111105
Open
Description
opened on May 2, 2023
I tried this code:
#![feature(return_position_impl_trait_in_trait)]
use std::future::Future;
pub trait Foo: Sync {
fn run<'a, 'b: 'a, T: Sync>(&'a self, _: &'b T) -> impl Future<Output = ()> + 'a + Send; // doesn't compile
// fn run<'a, 'b, T: Sync>(&'a self, _: &'b T) -> impl Future<Output = ()> + 'a + Send; // compiles
}
pub trait FooExt: Foo {
fn run_via<'a, 'b: 'a, T: Sync>(&'a self, t: &'b T) -> impl Future<Output = ()> + 'a + Send {
async move {
// asks for an unspecified lifetime to outlive itself? weird diagnostics
self.run(t).await;
}
}
}
I expected to see this happen: successful compilation
Instead, this happened: an outlives lifetime error with very bad diagnostics
error: lifetime bound not satisfied
--> src/lib.rs:12:9
|
12 | / async move {
13 | | // asks for an unspecified lifetime to outlive itself? weird diagnostics
14 | | self.run(t).await;
15 | | }
| |_________^
|
note: the lifetime defined here...
--> src/lib.rs:14:18
|
14 | self.run(t).await;
| ^^^
note: ...must outlive the lifetime defined here
--> src/lib.rs:14:18
|
14 | self.run(t).await;
| ^^^
= note: this is a known limitation that will be removed in the future ([see issue #100013 <https://github.com/rust-lang/rust/issues/100013>](https://github.com/rust-lang/rust/issues/100013) for more information)
Then I tried this code:
pub trait Foo: Sync {
fn run<'a, 'b: 'a, T: Sync>(&'a self, _: &'b T) -> impl Future<Output = ()> + 'a;
}
pub trait FooExt: Foo {
fn run_via<'a, 'b: 'a, T: Sync>(&'a self, t: &'b T) -> impl Future<Output = ()> + 'a {
async move {
self.run(t).await; // compiles now!
}
}
}
And the code compiled! Seems like Send
bound on the return impl trait type in run
function breaks borrow checker in some way, or possibly breaks inner definition of the anonymous impl type since the following code with a trait object works.
#![feature(return_position_impl_trait_in_trait)]
use std::{pin::Pin, future::Future};
pub trait Foo: Sync {
fn run<'a, 'b: 'a, T: Sync>(&'a self, _: &'b T) -> Pin<Box<dyn Future<Output = ()> + 'a + Send>>;
}
pub trait FooExt: Foo {
// this function still has a RPITIT
fn run_via<'a, 'b: 'a, T: Sync>(&'a self, t: &'b T) -> impl Future<Output = ()> + 'a + Send {
async move {
// works!
self.run(t).await;
}
}
}
-Ztrait-solver=next
and polonius
First code snippet leads to an ICE when using -Ztrait-solver=next
, I am not sure whether it's worth filing an ICE report right now because this is a bug in the default solver. As for polonius, it doesn't change anything.
Meta
rustc --version --verbose
:
rustc 1.71.0-nightly (dbba59457 2023-05-01)
binary: rustc
commit-hash: dbba594575ce75b1b57ccb1e4223b9909a28b1b8
commit-date: 2023-05-01
host: x86_64-unknown-linux-gnu
release: 1.71.0-nightly
LLVM version: 16.0.2
Metadata
Assignees
Labels
Type
Projects
Status
No status
Activity