4

The following code generates an error:

struct IntParseVisitor<'de, V: Visitor<'de>> {
    inner_visitor: V,
}

pub trait Visitor<'de>: Sized {
    fn visit_str<E>(self, v: &'de str) {}
}
error[E0392]: parameter `'de` is never used
 --> src/lib.rs:1:24
  |
1 | struct IntParseVisitor<'de, V: Visitor<'de>> {
  |                        ^^^ unused parameter
  |
  = help: consider removing `'de`, referring to it in a field, or using a marker such as `std::marker::PhantomData`

I don't quite understand how it is unused. Is it not used for Visitor<'de>? What's the best way of fixing this? Note that I can't change the code for Visitor since it is in Serde.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • `struct IntParseVisitor<'de, V: Visitor<'_>> { inner_visitor: V, } `? If not use PhamtomData as suggested – Netwave Aug 03 '20 at 12:42
  • It looks like your question might be answered by the answers of [How does for<> syntax differ from a regular lifetime bound?](https://stackoverflow.com/q/35592750/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 03 '20 at 12:57
  • 1
    Actually that answer did not provide enough information to get `for<>` working in my actual code, whereas `PhantomData` did work, so I don't think it is a duplicate. Also that answer is about generic arguments to functions. It isn't clear how it applies to structs. Please give more benefit of the doubt when closing questions in future thank you. – Timmmm Aug 03 '20 at 13:54

2 Answers2

3

Ah, thanks to @Shepmaster's hint I tried this, which compiles:

struct IntParseVisitor<V: for<'de> Visitor<'de>> {
    inner_visitor: V,
}

pub trait Visitor<'de>: Sized {
    fn visit_str<E>(self, v: &'de str)
    {
    }
}

I don't fully understand the lifetimes here so don't take my word for it.

Timmmm
  • 88,195
  • 71
  • 364
  • 509
1

You can follow the error suggestion:

help: consider removing 'de, referring to it in a field, or using a marker such as std::marker::PhantomData

struct IntParseVisitor<'de, V: Visitor<'de>> {
    inner_visitor: V,
    _phantom_data: std::marker::PhantomData<&'de ()>,
}
Netwave
  • 40,134
  • 6
  • 50
  • 93
  • This worked with the rest of my code, so I think this is the best answer. I could not get `for<'de>` to work with the `serde::de::Visitor::Type` associated type when I actually tried it with my code. Thanks! – Timmmm Aug 03 '20 at 13:52
  • My intuition, which may be wrong, says that `PhantomData` is more correct. The semantics of `Visitor` are those of a function that takes `'de` in an argument. Traits don't actually have variance but if they did that would be contravariant. Using a covariant `PhantomData` probably limits the use of `IntParseVisitor` artificially. (But it is still more likely that HRTBs are the actual desired solution here.) – trent Aug 03 '20 at 14:34