Skip to content

Instantly share code, notes, and snippets.

@jpastuszek
Forked from rust-play/playground.rs
Last active December 20, 2022 15:04
Show Gist options
  • Save jpastuszek/41fb5073dec33cae431ef25f8b576ac1 to your computer and use it in GitHub Desktop.
Save jpastuszek/41fb5073dec33cae431ef25f8b576ac1 to your computer and use it in GitHub Desktop.
Return impl Trait generic trainsient borrow
#![feature(type_alias_impl_trait)]
use std::io::Read;
use std::io::Cursor;
struct B(String);
struct RefPairA<'b>(&'b B, String);
trait GetPair {
fn pair(&self) -> (&str, &str);
}
impl<'b> GetPair for RefPairA<'b> {
fn pair(&self) -> (&'b str, &str) {
(&self.0.0, &self.1)
}
}
fn get_data_a(p: &RefPairA) -> impl Read {
let (b, s) = p.pair();
Cursor::new(format!("{}/{}", b, s).into_bytes())
}
fn get_data_generic(p: &impl GetPair) -> Cursor<Vec<u8>> {
let (b, s) = p.pair();
Cursor::new(format!("{}/{}", b, s).into_bytes())
}
fn get_data_generic_box(p: &impl GetPair) -> Box<dyn Read> {
let (b, s) = p.pair();
Box::new(Cursor::new(format!("{}/{}", b, s).into_bytes()))
}
type Ret = impl Read;
fn get_data_generic_read_alias(p: &impl GetPair) -> Ret {
let (b, s) = p.pair();
Cursor::new(format!("{}/{}", b, s).into_bytes())
}
// captures GetPair inner lifetime in return type
fn get_data_generic_read(p: &impl GetPair) -> impl Read {
let (b, s) = p.pair();
Cursor::new(format!("{}/{}", b, s).into_bytes())
}
// captures GetPair inner lifetime in return type
fn get_data_generic_read2<GP: GetPair>(p: &GP) -> impl Read {
let (b, s) = p.pair();
Cursor::new(format!("{}/{}", b, s).into_bytes())
}
fn data_a() -> impl Read {
let b = B("foo".to_owned());
let a = RefPairA(&b, "bar".to_owned());
get_data_a(&a)
}
fn data_generic() -> impl Read {
let b = B("foo".to_owned());
let a = RefPairA(&b, "bar".to_owned());
get_data_generic(&a)
}
fn data_generic_box() -> impl Read {
let b = B("foo".to_owned());
let a = RefPairA(&b, "bar".to_owned());
get_data_generic_box(&a)
}
fn data_generic_read_alias() -> Ret {
let b = B("foo".to_owned());
let a = RefPairA(&b, "bar".to_owned());
get_data_generic_read_alias(&a)
}
// //error[E0597]: `b` does not live long enough
// fn data_generic_read() -> impl Read {
// let b = B("foo".to_owned());
// let a = RefPairA(&b, "bar".to_owned());
// get_data_generic_read(&a)
// // --------- argument requires that `b` is borrowed for `'static`
// }
// // error[E0597]: `b` does not live long enough
// fn data_generic_read2() -> impl Read {
// let b = B("foo".to_owned());
// let a = RefPairA(&b, "bar".to_owned());
// get_data_generic_read2(&a)
// // --------- argument requires that `b` is borrowed for `'static`
// }
// https://users.rust-lang.org/t/impl-trait-lifetime-in-return-position/72514
// https://rust-lang.github.io/impl-trait-initiative/explainer/rpit_capture.html
// https://github.com/rust-lang/rust/issues/105826
// similar issue: https://github.com/rust-lang/rust/issues/98997
// bingo: https://github.com/rust-lang/rust/issues/82171#issuecomment-779997655
// "There's no way currently to express that an impl Trait doesn't capture
// all the input lifetimes. Once type Ret<'a> = impl Trait + 'a; is stabilized
// you could express the behavior you're looking for, but for now the only
// option are the ones identified in the report (explicit type and Box<dyn Trait>)."
// https://github.com/rust-lang/rust/issues/79415
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment