I have this code:
use std::fmt::Debug;
struct S<A>
where
for<'a> A: Debug + 'a,
{
f: Box<Fn(A) -> i32>,
}
impl<A> S<A>
where
for<'a> A: Debug + 'a,
{
fn call(&self, a: A) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A>(f: Box<Fn(A) -> i32>) -> S<A>
where
for<'a> A: Debug + 'a,
{
S::<A> { f }
}
fn helper() {
let x = create::<&i32>(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
let x = helper();
}
It's failed to compile:
error[E0310]: the parameter type `A` may not live long enough
In code 2, I changed Fn(A) -> i32 to Fn(&A) -> i32, the code works.
...
f: Box<Fn(&A) -> i32>,
...
Since A is argument of Fn trait, it's a type that has Higher-Rank lifetime. It shouldn't be affected by the lifetime of struct S<A> .
But why can't code 1 be compiled?
How can I workaround it for borrow or non-borrow type A?
There is no easy way to make helper work in current Rust, even if you remove all the for<'a> A: Debug + 'a, bounds (which only further restricts what types A can be, whereas you want to allow more).
This is as simple as I can make your example:
struct S<A> {
f: Box<Fn(A) -> i32>,
}
impl<A> S<A> {
fn call(&self, a: A) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A>(f: Box<Fn(A) -> i32>) -> S<A> {
S { f }
}
fn helper() {
let x = create(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
helper();
}
The reason it doesn't work is that A "comes from the outside", and Rust can't infer that you want for<'a> S<&'a A>, it can't even talk about such a type.
Note that if let arg = 333; is placed above let x, this example does compile (because it infers a reference to arg specifically, not a for<'a>).
The closest you can get today is with an associated type on a trait with a lifetime parameter, e.g.:
// Emulating `type Type<'a>` by moving `'a` to the trait.
trait Apply<'a> {
type Type;
}
struct Plain<T>(std::marker::PhantomData<T>);
impl<'a, T> Apply<'a> for Plain<T> {
type Type = T;
}
struct Ref<T: ?Sized>(std::marker::PhantomData<T>);
impl<'a, T: ?Sized + 'a> Apply<'a> for Ref<T> {
type Type = &'a T;
}
struct S<A: for<'a> Apply<'a>> {
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
}
impl<A: for<'a> Apply<'a>> S<A> {
fn call<'a>(&self, a: <A as Apply<'a>>::Type) {
println!("Return {:?}", (self.f)(a));
}
}
fn create<A: for<'a> Apply<'a>>(
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
) -> S<A> {
S { f }
}
fn helper() {
let x = create::<Ref<i32>>(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}
fn main() {
helper();
}
However, it turns out that this encoding hits https://github.com/rust-lang/rust/issues/52812, so it's not actually usable at the moment (and I'm not aware of an workaround).
Related
I am trying to implement a Visitor pattern in Rust.
I am not able to find a way to support two visitors which return different return value types.
Playground link
trait Visited<R> {
fn accept (self: &Self, v: &dyn Visitor<R>) -> R;
}
trait Visitor<R> {
fn visit_a(&self, a: &A<R>) -> R;
fn visit_b(&self, b: &B) -> R;
}
I've implemented two data structures that can be visited.
// ---- A ----
struct A<R> {
value: String,
b: Box<dyn Visited<R>>,
}
impl<R> Visited<R> for A<R> {
fn accept (&self, v: &dyn Visitor<R>) -> R {
v.visit_a(self)
}
}
// ---- B ----
struct B {
value: i32,
}
impl<R> Visited<R> for B {
fn accept(&self, v: &dyn Visitor<R>) -> R {
v.visit_b(self)
}
}
This worked okay when I just had a concrete visitor.
struct Visitor1 {}
impl Visitor<String> for Visitor1 {
fn visit_a(&self, a: &A<String>) -> String {
let b = a.b.accept(self);
format!("visitor1.visit_a(): {} {}", a.value, b)
}
fn visit_b(&self, b: &B) -> String {
format!("visitor1.visit_b(): {}", b.value)
}
}
However, the whole point of the Visitor pattern is to let multiple algorithm to be applied against the data structure.
When I wanted to add another visitor, I couldn't figure out how to make it work.
struct Visitor2 {}
impl Visitor<i32> for Visitor2 {
fn visit_a(&self, a: &A<i32>) -> i32 {
123
}
fn visit_b(&self, b: &B) -> i32 {
456
}
}
fn main() {
let a = A {
value: "HELLO".to_string(),
b: Box::new(B{ value: 32 })
};
let v1 = Visitor1{};
let s: String = a.accept(&v1);
println!("{}", s);
let v2 = Visitor2{};
let v: i32 = a.accept(&v2);
println!("{}", v);
}
The type of a is inferred as A<String>, and the a.accept(&v2) caused a type mismatch error.
I'd like to tell a to be visited by Visitor1 and Visitor2. How can I do this?
If you return only 'static types, you can use type erasure. The idea is to create a trait, ErasedVisitor, that is not generic and instead return Box<dyn Any>, and implement this trait for all Visitors and use it internally. This mean, though, that you cannot use a generic parameter, only an associated type (otherwise you get "unconstrained type parameter":
trait Visited {
fn accept_dyn(&self, v: &dyn ErasedVisitor) -> Box<dyn Any>;
fn accept<V: Visitor>(&self, v: &V) -> V::Result
where
Self: Sized,
{
*self.accept_dyn(v).downcast().unwrap()
}
}
impl<T: ?Sized + Visited> Visited for &'_ T {
fn accept_dyn(&self, v: &dyn ErasedVisitor) -> Box<dyn Any> {
T::accept_dyn(&**self, v)
}
}
impl<T: ?Sized + Visited> Visited for &'_ mut T {
fn accept_dyn(&self, v: &dyn ErasedVisitor) -> Box<dyn Any> {
T::accept_dyn(&**self, v)
}
}
impl<T: ?Sized + Visited> Visited for Box<T> {
fn accept_dyn(&self, v: &dyn ErasedVisitor) -> Box<dyn Any> {
T::accept_dyn(&**self, v)
}
}
trait Visitor {
type Result: 'static;
fn visit_a(&self, a: &A) -> Self::Result;
fn visit_b(&self, b: &B) -> Self::Result;
}
trait ErasedVisitor {
fn visit_a(&self, a: &A) -> Box<dyn Any>;
fn visit_b(&self, b: &B) -> Box<dyn Any>;
}
impl<V: ?Sized + Visitor> ErasedVisitor for V {
fn visit_a(&self, a: &A) -> Box<dyn Any> {
Box::new(<Self as Visitor>::visit_a(self, a))
}
fn visit_b(&self, b: &B) -> Box<dyn Any> {
Box::new(<Self as Visitor>::visit_b(self, b))
}
}
struct A {
value: String,
b: Box<dyn Visited>,
}
impl Visited for A {
fn accept_dyn(&self, v: &dyn ErasedVisitor) -> Box<dyn Any> {
v.visit_a(self)
}
}
Playground.
But if you can, the best way is to use static polymorphism (generics) instead of dynamic dispatch.
If you want your Visited trait to support multiple return types, you cannot tie the return type to the object itself. Currently, the return type is a generic, so every object has the return type hard-coded into it.
To solve this, you can remove the return type generic from the Visited trait and instead attach it to the accept function.
This has one drawback though: You can no longer create trait objects with this trait. That makes sense, because once cast to a dyn Visited, Rust no longer knows which type it is, making it impossible for the compiler to compile the accept function for all required types. It looses the knowledge between the compilated function and the types that it will get called with.
Normally, this is fine, but in your case, A holds a Box<dyn Visited>. This is impossible, due to the reasons described above.
So if we change Box<dyn Visited> to B, (and do some refactoring with the generics), we can get it to work:
trait Visited {
fn accept<V: Visitor>(&self, v: &V) -> V::Ret;
}
trait Visitor {
type Ret;
fn visit_a(&self, a: &A) -> Self::Ret;
fn visit_b(&self, b: &B) -> Self::Ret;
}
// ---- A ----
struct A {
value: String,
b: B,
}
impl Visited for A {
fn accept<V: Visitor>(&self, v: &V) -> V::Ret {
v.visit_a(self)
}
}
// ---- B ----
struct B {
value: i32,
}
impl Visited for B {
fn accept<V: Visitor>(&self, v: &V) -> V::Ret {
v.visit_b(self)
}
}
struct Visitor1 {}
impl Visitor for Visitor1 {
type Ret = String;
fn visit_a(&self, a: &A) -> String {
let b = a.b.accept(self);
format!("visitor1.visit_a(): {} {}", a.value, b)
}
fn visit_b(&self, b: &B) -> String {
format!("visitor1.visit_b(): {}", b.value)
}
}
struct Visitor2 {}
impl Visitor for Visitor2 {
type Ret = i32;
fn visit_a(&self, _a: &A) -> i32 {
123
}
fn visit_b(&self, _b: &B) -> i32 {
456
}
}
fn main() {
let a = A {
value: "HELLO".to_string(),
b: B { value: 32 },
};
let v1 = Visitor1 {};
let s: String = a.accept(&v1);
println!("{}", s);
let v2 = Visitor2 {};
let v: i32 = a.accept(&v2);
println!("{}", v);
}
visitor1.visit_a(): HELLO visitor1.visit_b(): 32
123
We can make this a little more convenient and make the actual type a generic of A. In contrast to a dyn Visited, this allows Rust to resolve its exact type at compile time, making it possible to compile it.
trait Visited {
fn accept<V: Visitor>(&self, v: &V) -> V::Ret;
}
trait Visitor {
type Ret;
fn visit_a<T: Visited>(&self, a: &A<T>) -> Self::Ret;
fn visit_b(&self, b: &B) -> Self::Ret;
}
// ---- A ----
struct A<T> {
value: String,
b: T,
}
impl<T: Visited> Visited for A<T> {
fn accept<V: Visitor>(&self, v: &V) -> V::Ret {
v.visit_a(self)
}
}
// ---- B ----
struct B {
value: i32,
}
impl Visited for B {
fn accept<V: Visitor>(&self, v: &V) -> V::Ret {
v.visit_b(self)
}
}
struct Visitor1 {}
impl Visitor for Visitor1 {
type Ret = String;
fn visit_a<T: Visited>(&self, a: &A<T>) -> String {
let b = a.b.accept(self);
format!("visitor1.visit_a(): {} {}", a.value, b)
}
fn visit_b(&self, b: &B) -> String {
format!("visitor1.visit_b(): {}", b.value)
}
}
struct Visitor2 {}
impl Visitor for Visitor2 {
type Ret = i32;
fn visit_a<T: Visited>(&self, _a: &A<T>) -> i32 {
123
}
fn visit_b(&self, _b: &B) -> i32 {
456
}
}
fn main() {
let a = A {
value: "HELLO".to_string(),
b: B { value: 32 },
};
let v1 = Visitor1 {};
let s: String = a.accept(&v1);
println!("{}", s);
let v2 = Visitor2 {};
let v: i32 = a.accept(&v2);
println!("{}", v);
}
visitor1.visit_a(): HELLO visitor1.visit_b(): 32
123
I was playing with the code from this answer but the FromIterator impl does not compile any more:
error[E0276]: impl has stricter requirements than trait --> src/lib.rs:184:9
| 184 | fn from_iter<I: IntoIterator<Item = T> + 'a>(itrbl: I) -> LazyList<'a, T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `I: 'a`
For more information about this error, try `rustc --explain E0276`.
The slightly updated code is on the playground.
// only necessary because Box<FnOnce() -> R> doesn't work...
mod thunk {
pub trait Invoke<R = ()> {
fn invoke(self: Box<Self>) -> R;
}
impl<R, F: FnOnce() -> R> Invoke<R> for F {
#[inline(always)]
fn invoke(self: Box<F>) -> R { (*self)() }
}
}
// Lazy is lazily evaluated contained value using the above Invoke trait
// instead of the desire Box<FnOnce() -> T> or a stable FnBox (currently not)...
pub mod lazy {
use crate::thunk::Invoke;
use std::cell::UnsafeCell;
use std::mem::replace;
use std::ops::Deref;
// Lazy is lazily evaluated contained value using the above Invoke trait
// instead of the desire Box<FnOnce() -> T> or a stable FnBox (currently not)...
pub struct Lazy<'a, T: 'a>(UnsafeCell<LazyState<'a, T>>);
enum LazyState<'a, T: 'a> {
Unevaluated(Box<dyn Invoke<T> + 'a>),
EvaluationInProgress,
Evaluated(T),
}
use self::LazyState::*;
impl<'a, T: 'a> Lazy<'a, T> {
#[inline]
pub fn new<F: 'a + FnOnce() -> T>(func: F) -> Lazy<'a, T> {
Lazy(UnsafeCell::new(Unevaluated(Box::new(func))))
}
#[inline]
pub fn evaluated(val: T) -> Lazy<'a, T> {
Lazy(UnsafeCell::new(Evaluated(val)))
}
#[inline(always)]
fn force(&self) {
unsafe {
match *self.0.get() {
Evaluated(_) => {}, // nothing required; already Evaluated
EvaluationInProgress => panic!("Lazy::force called recursively!!!"),
_ => {
let ue = replace(&mut *self.0.get(), EvaluationInProgress);
if let Unevaluated(thnk) = ue {
*self.0.get() = Evaluated(thnk.invoke());
} // no other possiblity!
}
}
}
}
#[inline]
pub fn unwrap<'b>(self) -> T where T: 'b { // consumes the object to produce the value
self.force(); // evaluatate if not evealutated
match { self.0.into_inner() } {
Evaluated(v) => v,
_ => unreachable!() // previous code guarantees never not Evaluated
}
}
}
impl<'a, T: 'a> Deref for Lazy<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.force(); // evaluatate if not evalutated
match *unsafe { &*self.0.get() } {
Evaluated(ref v) => v,
_ => unreachable!(),
}
}
}
}
// LazyList is an immutable lazily-evaluated persistent (memoized) singly-linked list
// similar to lists in Haskell, although here only tails are lazy...
// depends on the contained type being Clone so that the LazyList can be
// extracted from the reference-counted Rc heap objects in which embedded.
pub mod lazylist {
use crate::lazy::Lazy;
use std::rc::Rc;
use std::iter::FromIterator;
use std::mem::{replace, swap};
#[derive(Clone)]
pub enum LazyList<'a, T: 'a + Clone> {
Empty,
Cons(T, RcLazyListNode<'a, T>),
}
pub use self::LazyList::Empty;
use self::LazyList::Cons;
type RcLazyListNode<'a, T> = Rc<Lazy<'a, LazyList<'a, T>>>;
// impl<'a, T:'a> !Sync for LazyList<'a, T> {}
impl<'a, T: 'a + Clone> LazyList<'a, T> {
#[inline]
pub fn singleton(v: T) -> LazyList<'a, T> {
Cons(v, Rc::new(Lazy::evaluated(Empty)))
}
#[inline]
pub fn cons<F>(v: T, cntf: F) -> LazyList<'a, T>
where F: 'a + FnOnce() -> LazyList<'a, T>
{
Cons(v, Rc::new(Lazy::new(cntf)))
}
#[inline]
pub fn head(&self) -> &T {
if let Cons(ref hd, _) = *self {
return hd;
}
panic!("LazyList::head called on an Empty LazyList!!!")
}
#[inline]
pub fn tail<'b>(&'b self) -> &'b Lazy<'a, LazyList<'a, T>> {
if let Cons(_, ref rlln) = *self {
return &*rlln;
}
panic!("LazyList::tail called on an Empty LazyList!!!")
}
#[inline]
pub fn unwrap(self) -> (T, RcLazyListNode<'a, T>) {
// consumes the object
if let Cons(hd, rlln) = self {
return (hd, rlln);
}
panic!("LazyList::unwrap called on an Empty LazyList!!!")
}
#[inline]
fn iter(&self) -> Iter<'a, T> {
Iter(self)
}
}
impl<'a, T: 'a + Clone> Iterator for LazyList<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match replace(self, Empty) {
Cons(hd, rlln) => {
let mut newll = (*rlln).clone();
swap(self, &mut newll); // self now contains tail, newll contains the Empty
Some(hd)
}
_ => None,
}
}
}
pub struct Iter<'a, T: 'a + Clone>(*const LazyList<'a, T>);
impl<'a, T: 'a + Clone> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
if let LazyList::Cons(ref v, ref r) = *self.0 {
self.0 = &***r;
Some(v)
} else {
None
}
}
}
}
impl<'i, 'l, T: 'i + Clone> IntoIterator for &'l LazyList<'i, T> {
type Item = &'i T;
type IntoIter = Iter<'i, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T: 'a + Clone, > FromIterator<T> for LazyList<'a, T> {
fn from_iter<I: IntoIterator<Item = T> + 'a>(itrbl: I) -> LazyList<'a, T> {
let itr = itrbl.into_iter();
#[inline(always)]
fn next_iter<'b, R, Itr>(mut iter: Itr) -> LazyList<'b, R>
where R: 'b + Clone,
Itr: 'b + Iterator<Item = R>
{
match iter.next() {
Some(val) => LazyList::cons(val, move || next_iter(iter)),
None => Empty,
}
}
next_iter(itr)
}
}
}
Unfortunately I've exhausted ideas on how to try and fix this.
The code in the question (though not in the referenced answer, which has since been updated) relies on a soundness bug in older versions of the compiler (#18937) which has since been fixed.
It is not possible to implement FromIterator for LazyList, or indeed for any data structure, by storing the iterator inside the structure. This is because the FromIterator trait allows the implementor (Self) to outlive the iterator type (I::IntoIter). That the compiler ever accepted it was an oversight.
When copying code from the internet, be conscious of the age of the source. This code is also out of date in several other respects, notably:
it uses Rust 2015-style paths
it omits dyn on trait object types
the Invoke workaround is no longer needed, since dyn FnOnce() -> T works properly now.
I want to have a trait that can be implemented for T and &T but has methods that always return T.
What I would like to do is something like this
use std::borrow::ToOwned;
trait Foo<X: ToOwned> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Owned;
}
struct Float(f64);
impl Foo<f64> for Float {
fn f(&self, x: f64) -> f64 {
x + self.0
}
fn g(&self) -> f64 {
self.0 * 2.0
}
}
struct List(Vec<f64>);
impl Foo<&Vec<f64>> for List {
fn f(&self, x: &Vec<f64>) -> f64 {
x.iter().sum()
}
// Error here - `&Vec<f64>` return type expected
fn g(&self) -> Vec<f64> {
self.0.iter().map(|&x| 2.0 * x).collect()
}
}
fn main() {
let float = Float(2.0);
println!("{} {}", float.f(3.0), float.g());
let list = List(vec![0.0, 1.0, 2.0]);
println!("{} {:?}", list.f(&vec![1.0, 2.0]), list.g());
}
I know that one option is to have a trait that defines the output type like so
trait FooReturn {
type Output;
}
trait Foo<X: FooReturn> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Output;
}
then implement the trait for all relevant types, but I was wondering if there was a more standard/robust way to do this.
This is how you would do it once specialization is complete. Meanwhile, I couldn't even get a simple working example to compile on 1.55.0-nightly.
#![feature(specialization)]
trait MaybeOwned {
type Owned;
}
default impl<X> MaybeOwned for X {
type Owned = X;
}
impl<'a, X> MaybeOwned for &'a X {
type Owned = X;
}
trait Foo<X: MaybeOwned> {
fn f(&self, x: &X) -> f64;
fn g(&self) -> <X as MaybeOwned>::Owned;
}
How can I reduce the lifetime of a closure?
I was trying to make a method, which returns an iterator related to self. I didn't want to make new struct or something, so I just made it return filters and maps, and confronted some borrow checker errors.
The following code was my first try.
fn f<'b>(&'b self) -> impl Iterator<Item = u8> {
(0..self.some_number())
.filter(|&i| self.some_bool_function(i))
.map(|i| i as u8)
}
The following code replicates my question.
struct A(bool);
impl A {
fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
(0..1).filter(|&i| self.0)
}
}
or even shorter,
fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
|| *t
}
This would not compile, because the closure may outlive self. I don't know how to make this work, without moving self.
If you return a closure, you must ensure that the closure has everything it needs - even after returning (i.e. after the (temporary) function parameters are popped from the stack).
Thus, I think you want to move the stuff you return into the closure:
impl A {
fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
(0..1).filter(move |&i| self.0)
}
}
Resp.
fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
move || *t
}
Resp (extending your first example):
struct A(bool);
impl A {
fn some_number(&self) -> usize {
6
}
fn some_bool_function(&self, i: usize) -> bool {
i%2==0
}
fn f<'b>(&'b self) -> impl Iterator<Item = u8> + 'b {
(0..self.some_number())
.filter(move |&i| self.some_bool_function(i))
.map(|i| i as u8)
}
}
There is some minimal example library code I would like to use:
struct MyR<'a> {
x: &'a str,
}
struct T {
x: &'static str,
}
impl T {
fn bar<'a>(&'a self) -> MyR {
MyR { x: self.x }
}
}
The following is my code:
trait A<R, F: FnMut(&R)> {
fn foo(&mut self, callback: &mut F);
}
impl<'a, F> A<MyR<'a>, F> for T
where F: FnMut(&MyR<'a>)
{
fn foo(&mut self, callback: &mut F) {
let t = T { x: "l" };
let r = t.bar(); // t does not live long enough (for 'a)
callback(&r);
println!("abc");
}
}
fn test() {
let mut t = T { x: "l" };
let mut i = 1;
t.foo(&mut |x| { i += x.x.len(); });
}
I would like to make a trait that is parametrized by the callback, but I struggled to make it right. If I don't use a trait, it works well:
impl T {
fn foo<F: FnMut(&MyR)>(&mut self, callback: &'a mut F) {
let t = T { x: "l" };
let r = t.bar();
callback(&r);
println!("abc");
}
}
But I cannot do this:
impl T {
fn foo<'a, F: FnMut(&MyR<'a>)>(&mut self, callback: &mut F) {
let t = T { x: "l" };
let r = t.bar();
callback(&r);
println!("abc");
}
}
I know the problem is that t must outlive 'a, but I don't know to bound 'a so that its lifetime is shorter than t.
I'm using rustc 1.19.0-nightly.
Read the error messages:
t does not live long enough — it lives until the end of the foo function.
borrowed value must be valid for the lifetime 'a — you have specified 'a:
impl<'a, F> A<MyR<'a>, F> for T
where F: FnMut(&MyR<'a>)
This says that for any possible lifetime, the trait will be implemented, so long as F implements the FnMut trait.
There's only one possible way to make that work — you have to have a MyR that is parameterized with the 'static lifetime. That's the only lifetime that is guaranteed to outlive any arbitrary lifetime.
Let's see where MyR comes from:
fn bar<'a>(&'a self) -> MyR {
MyR { x: self.x }
}
If you go back and reread The Rust Programming Language section on lifetime elision, you'll recognize that this lifetime specification provides no value. It defines a lifetime and uses it with self, but it's never tied to any output lifetimes. The code is the same as:
fn bar<'a, 'b>(&'a self) -> MyR<'b>
If you removed the lifetime, then you'd have
fn bar(&self) -> MyR
fn bar<'a>(&'a self) -> MyR<'a> // equivalent
However, neither of these is the 'static lifetime. Luckily for you, you know that that x is a &'static str, so you can just reflect that in your signature and the code will compile:
fn bar(&self) -> MyR<'static>
Spending hours trying different approaches, this seems to work
trait A<F> {
fn foo(&mut self, callback: &mut F);
}
impl<F> A<F> for T
where F: FnMut(&MyR)
{
fn foo(&mut self, callback: &mut F) {
let t = T { x: "l" };
let r = t.bar(); // t does not live long enough (for 'a)
callback(&r);
println!("abc");
}
}
fn main() {
let mut t = T { x: "l" };
let mut i = 1;
t.foo(&mut |x: &MyR| { i += x.x.len(); });
}
The main difference is:
I have to loose trait a bit so that it takes arbitrary types.
So that when I impl I don't have to specify lifetime at all.
I have to type annotate the closure when invoking the function.
Playground