1

I'm trying to require a generic type to be indexable by const ref to another generic:

struct A<T, I> where T: Index<&I> {
    t: T,
    some_more_uses_of_I...
}

it does not compile asking me to provide a lifetime for &I. When I change it into &'_ I compiler complains that "'_ cannot be used here" and "'_ is a reserved lifetime name". How can I make it work? To my understanding there is no real need for the lifetime, the reference must be alive only during execution of [] and I belive I shouldn't tie it to any other object.

Dekakaruk
  • 661
  • 1
  • 8
  • 13
  • 1
    Hard to say without a more complete example, but you can probably get what you want if you move the `where` clause to the `impl` block. This way: `impl<'a, T, I> A where T: Index<&'a I>` the lifetime is not linked to the struct `A` itself. – Jmb Sep 23 '21 at 13:28

2 Answers2

2

Without knowing exactly how you're using this struct, its hard to say. But it sounds like you could use a higher-ranked trait bound such that the constraint is generic over the lifetime:

struct A<T, I> 
where 
    T: for<'a> Index<&'a I>
{
    t: T,
    some_more_uses_of_I...
}
kmdreko
  • 42,554
  • 6
  • 57
  • 106
  • 2
    @Dekakaruk If you don't get error messages with this code, it probably means that you're not actually using `Index<&I>` inside the struct, and should therefore not have a bound here (as I also mentioned in my comment on the other answer). If the bound is actually necessary - that is, if you're using `Index<&'x I>` in the struct definition - then `'x` has to be (1) a struct parameter as in the other answer, (2) `'static`, or (3) part of another HRTB in the struct definition. If none of those is the case I recommend deleting the bound. – trent Sep 23 '21 at 19:34
1

This should be compile

struct A<'a, T, I>
    where T: Index<&'a I> {
        t: T
    }

You can see more about in https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-annotations-in-struct-definitions

Zeppi
  • 1,175
  • 6
  • 11
  • "the parameter type `I` may not live long enough", "help: consider adding an explicit lifetime bound...: `I: 'a`". I don't know lifetime specifiers very well, but to the extent of my knowledge t it would require he reference to outlive A, which is not intended – Dekakaruk Sep 23 '21 at 11:46
  • This post can help you better perhaps, https://stackoverflow.com/questions/27589054/what-is-the-correct-way-to-use-lifetimes-with-a-struct-in-rust – Zeppi Sep 23 '21 at 11:52
  • Sorry, I don't see relation. My problem is how to indicate that the lifetime has nothing to do with anything, or at least to understand why it is needed – Dekakaruk Sep 23 '21 at 12:19
  • Sorry too, I'm not sure to understand. You can also declare "struct A {t: &'static str}", The "why" is called "lifetime elision" and is compiler requirement (https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#more-lifetime-elision-rules) – Zeppi Sep 23 '21 at 12:51
  • 1
    It's hard to say for sure without knowing more about @Dekakaruk's use case, but this could be an example of an inappropriate parameter due to misplacing the generic on the struct instead of the `impl`. I wrote about this at https://stackoverflow.com/a/66369912/3650362. Even if a bound is necessary, since it's relatively unlikely for `>::Output` to use `'a`, it probably makes more sense to use an HRTB here. But I repeat that not having a bound at all is probably the more semantically correct solution in most cases. – trent Sep 23 '21 at 19:23