0
votes

I tried to implement a trait for applying a function to all fields of struct trough an enum Variant, which should hopefully be always inlined at compilation. Sadly I am not able to figure out the lifetimes at all. The following code returns:

pub enum Variant<'a> { Str(&'a str), Int(usize) }

impl<'a> From<&'a str> for Variant<'a> {
    fn from(value: &'a str) -> Self {
        Variant::Str(value)
    }
}

pub struct Foo<T> { foo: T }

pub trait Foreach {
    fn foreach(&self, fun: impl FnMut(&Variant));
}


impl<'a,T:'a> Foreach for Foo<T> where &'a T: Into<Variant<'a>>{
    fn foreach(&'a self, fun: impl FnMut(&Variant<'a>)) {
        fun("Foo: ".into());
        fun(&(&self.foo).into()); // The variant should never escape this scope. The function should consume it immediately.
    }
}

Following error:

error[E0308]: method not compatible with trait
  --> src/lib.rs:17:5
   |
17 |     fn foreach(&'a self, fun: impl FnMut(&Variant<'a>)) {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
   |
   = note: expected fn pointer `fn(&Foo<T>, _)`
              found fn pointer `fn(&'a Foo<T>, _)`
note: the anonymous lifetime #1 defined on the method body at 17:5...
  --> src/lib.rs:17:5
   |
17 | /     fn foreach(&'a self, fun: impl FnMut(&Variant<'a>)) {
18 | |         fun("Foo: ".into());
19 | |         fun(&(&self.foo).into()); // The variant should never escape this scope. The function should consume it immediately.
20 | |     }
   | |_____^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 16:6
  --> src/lib.rs:16:6
   |
16 | impl<'a,T:'a> Foreach for Foo<T> where &'a T: Into<Variant<'a>>{
   |      ^^

error[E0277]: the trait bound `&Variant<'_>: std::convert::From<&str>` is not satisfied
  --> src/lib.rs:18:13
   |
18 |         fun("Foo: ".into());
   |             ^^^^^^^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `&Variant<'_>`
   |
   = help: the following implementations were found:
             <Variant<'a> as std::convert::From<&'a str>>
   = note: `std::convert::From<&str>` is implemented for `&mut Variant<'_>`, but not for `&Variant<'_>`
   = note: required because of the requirements on the impl of `std::convert::Into<&Variant<'_>>` for `&str`

1
I am inclined to link to the higher-rank trait bounds doc after looking at the question for 10 seconds. doc.rust-lang.org/nomicon/hrtb.htmlidursun
@idursun Thank you very much. Would you like to officially answer it?Ford O.
@FordO. posted an answer.idursun

1 Answers

1
votes

I think you can solve this by using Higher-rank trait bounds which is documented here

From the document:

for<'a> can be read as "for all choices of 'a", and basically produces an infinite list of trait bounds that F must satisfy.