A user reported the following issue:
https://github.com/rust-lang/rust/issues/41985
I noticed that in the latest draft of chapter 19, HRTBs are alluded to but never expanded upon:
There are three advanced features of lifetimes that we haven't covered though: lifetime subtyping, trait object lifetimes, and higher ranked trait bounds.
I think this user's frustration with these is that they are very poorly documented, and when they are mentioned, it is as though you'd never use them. I don't believe this is the case - probably any decent-sized project would need them at some point. I think it would be best if there were a couple of pages dedicated to their usage.
I think we just moved things around and never updated the intro for that section. I've just pushed a commit to make the headings and the intro match in both ordering and the terms they use.
We're still not mentioning the for <'x> &'x P: CanEncode syntax mentioned in the issue you linked to. I'm also unsure whether the "lifetime bounds" section is the same thing as HRTBs.... @steveklabnik can you clarify?
I don't believe this is the case - probably any decent-sized project would need them at some point.
I've worked on a few decent-sized Rust projects and haven't needed the for <'x> syntax, so this isn't particularly compelling for me.
HRTB == for<'a>
On Mon, May 15, 2017 at 8:37 PM, Carol (Nichols || Goulding) <
[email protected]> wrote:
I think we just moved things around and never updated the intro for that
section. I've just pushed a commit
https://github.com/rust-lang/book/commit/f93a17e00960f0f984c95a83be869f3ec71619f2
to make the headings and the intro match in both ordering and the terms
they use.We're still not mentioning the for <'x> &'x P: CanEncode syntax mentioned
in the issue you linked to. I'm also unsure whether the "lifetime bounds"
section is the same thing as HRTBs.... @steveklabnik
https://github.com/steveklabnik can you clarify?I don't believe this is the case - probably any decent-sized project would
need them at some point.I've worked on a few decent-sized Rust projects and haven't needed the for
<'x> syntax, so this isn't particularly compelling for me.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/book/issues/698#issuecomment-301642473, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AABsioZ0yDBX2QUcWYA0QWJlGpKsaPW5ks5r6O_bgaJpZM4NaN1l
.
HRTB == for<'a>
Ok, so no, we haven't covered that anywhere. Do you think we should @steveklabnik ?
IIRC, we did, and then decided to cut it, right?
I don't remember but that sounds consistent with my current position. Does this change your mind at all?
So, I definitely disagree with
I don't believe this is the case - probably any decent-sized project would need them at some point.
I have never written a HRTB, and when I tried to come up with an example that needed them, had a tough time doing so. The compiler and standard library, which is ~half a million LOC, has far more instances of them in tests and comments than it does in code; my rough count is something like ~40/~50 uses total. @withoutboats has said that it's a goal for them that you never need to actually write HRTB out.
However, I also can sympathize that leaving a bit of syntax out might be a disservice to our readers.
Basically, I am torn.
Ok, since neither of us feel strongly for it, I'm going to close this. We've always said we're not going to be comprehensive, and the Nomicon or other resources can go into this for people that need it.
Thank you for the discussion though @djzin!
I think the book is more appropriate for this than the Nomicon; this feature is advanced but it is not got to do with unsafe code, which I think is what the Nomicon is mostly about.
Because of a certain ellision (Fn(&T) is for<'a> Fn(&'a T)) you usually never have to write them. However, they are much more likely to appear if you have a trait parameterized by a lifetime; in particular, now that serde has Deserialize<'de> its much more likely that people will need this (though DeserializeOwned means essentially the same thing).
The big problem is that we have had some newer users trying to write really abstract code (usually because of their experience in Haskell, etc) and need them, and be very lost.
Do you have a good, easy example to show it off? That'd sway me a bit.
On Tue, May 16, 2017 at 3:25 PM, boats notifications@github.com wrote:
I think the book is more appropriate for this than the Nomicon; this
feature is advanced but it is not got to do with unsafe code, which I think
is what the Nomicon is mostly about.Because of a certain ellision (Fn(&T) is for<'a> Fn(&'a T)) you usually
never have to write them. However, they are much more likely to appear if
you have a trait parameterized by a lifetime; in particular, now that serde
has Deserialize<'de> its much more likely that people will need this
(though DeserializeOwned means essentially the same thing).The big problem is that we have had some newer users trying to write
really abstract code (usually because of their experience in Haskell, etc)
and need them, and be very lost.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/book/issues/698#issuecomment-301889185, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AABsioiRUL5BVmBKN7qKQCJ1Hcu-RUO2ks5r6fgugaJpZM4NaN1l
.
I'll try and come up with a nice example, in the meantime I thought I'd share this gem (nice and easy :D):
impl<'a>For for&'a for
<'b>For where for<'b>
For:For{fn four(&self)
{print!("for")}}fn main
(){four(&(four as for
<'b>fn(&'b for<'a>For))
)}trait For{fn four(&
self){}}fn four(four:&
for<'a>For){<&for<'a>
For as For>::four(&four
)}impl For for for<'b>
fn(&'b for<'a>For){}
Probably something which uses a higher order function is most appropriate.
Show this example:
fn foo<'a, F: Fn(&'a str)>(f: F) { /* call it on a reference you create inside this function */ }
You get an error. Change it to this:
fn foo<F: for<'a> Fn(&'a str)>(f: F) { ... }
It works. Explain what it means (easier said than done, I know).
Finish by mentioning that you can use this with any trait and that it this is what Fn trait elides references to by default.
@withoutboats only problem with that I see is introducing two concepts at the same time (desugaring of Fn and HRTBs proper). Might only add to confusion for a new user
Perhaps the simplest example I can give is using the AddAssign trait:
use std::ops::AddAssign;
// you can write this function like this
fn append_once<'a, T>(t: &mut T, s: &'a mut str)
where T: AddAssign<&'a mut str>
{
*t += s;
}
// but this one won't work! can't borrow mutably twice
/*fn append_twice<'a, T>(t: &mut T, s: &'a mut str)
where T: AddAssign<&'a mut str>
{
*t += s;
*t += s;
}*/
// you need HRTBs to make it work!
fn append_twice<T>(t: &mut T, s: &mut str)
where for<'a> T: AddAssign<&'a mut str>
// alternatively,
//where T: for<'a> AddAssign<&'a mut str>
{
*t += s;
*t += s;
}
(To be clear though, I don't mind keeping this issue closed (now that the wording has been changed in ch 19))
I just wanted to let you know that I just stumbled upon an HRTB in a codebase, but as there is close to no documentation on them I have no idea of what they are and how to implement them, and still as of right now am stuck with my issue.
I think having some form of official documentation on what they are is necessary because even if it's not frequently used, it's still a part of the language. Even the brief mention in the nomicon is very confusing because I think it assumes one already knows what HRTB are in the first place, and doesn't go at all into details on what the consequences are when trying to satisfy them.
Most helpful comment
I just wanted to let you know that I just stumbled upon an HRTB in a codebase, but as there is close to no documentation on them I have no idea of what they are and how to implement them, and still as of right now am stuck with my issue.
I think having some form of official documentation on what they are is necessary because even if it's not frequently used, it's still a part of the language. Even the brief mention in the nomicon is very confusing because I think it assumes one already knows what HRTB are in the first place, and doesn't go at all into details on what the consequences are when trying to satisfy them.