-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lifetime parameters on self + impl Traits requires unexpected workaround #80518
Comments
To answer your question: The reason you are seeing this issue is coming up because the closure is capturing a That's also effectively what the note attached to the diagnostic is saying. As for why the modified code worked – references of references imply an implicit "outlives" relationship that follows from some rules of the construct. For future reference there are a couple user support avenues that are more appropriate for asking questions: users.rlo, stackoverflow, reddit, or one of the chat platforms: discord or zulip. I'm going to close this out as not-a-bug, but if you think there's something that can be improved here complain and I'll reopen. |
Actually, I'm going to reopen this, as I myself felt somewhat unsure about the details in the answer above as I thought about it a little bit more. |
Thank you for the thorough answer here, I appreciate it. And apologies if I shouldn't have opened the issue in the first place. It's true that I wasn't sure if this was a bug or expected behavior, but I believe more clarity in the error message would still be helpful. As to your comments about relationship of the lifetimes: I didn't want to overload the initial issue with all the variations I've tried, but I see now that I should have provided more context. Firstly: if I add a bound of fn foo() {
let mut xorcism = Xorcism::new("hello".as_bytes());
xorcism.munge(&[1, 2, 3]);
xorcism.munge(&[1, 2, 3]);
} results in:
Adding
And changing the return type to: impl Iterator<Item=u8> + 'a + 'b results in:
Again, thank you for the thorough and quick response, and apologies for lack of clarity in the initial report. |
I don’t know the reasoning behind the compiler error when using In particular, impl<'a> Xorcism<'a> {
pub fn munge<'b, Data>(&'b mut self, data: Data) -> impl Iterator<Item=u8> + 'b;
} or equivalently (in terms of type-checking) as a freestanding function pub fn munge<'a, 'b, Data>(self: &'b Xorcism<'a>, data: Data) -> impl Iterator<Item=u8> + 'b; comes with an implicit The basics of By that logic, the return type of One way to mention the lifetime is in a trait bound: you could introduce a trait pub trait CaptureLifetime<'a> {}
impl<T: ?Sized> CaptureLifetime<'_> for T {} and then write impl<'a> Xorcism<'a> {
pub fn munge<'b, Data>(&'b mut self, data: Data) -> impl Iterator<Item=u8> + 'b + CaptureLifetime<'a>;
} Now, the lifetime Regarding the approach/workaround that you described: Instead of capturing a The difference that the fields introduce is that pub fn munge<'b, Data>(&'b mut self, data: Data) -> impl Iterator<Item=u8> + 'b
where
Data: IntoIterator,
Data::Item: Borrow<u8>,
Data::IntoIter: 'b,
{
let key = &mut self.key;
let index = &mut self.index;
data.into_iter().map(move |b| *b.borrow() ^ next_key(&*key, index))
} this doesn’t compile. The important step/change that made the compiler happy was in borrowing the field whose type contains the lifetime |
the return type needs to be owned-usable within both the
|
Thank you all for the responses here!
I completely missed this the first time around. Thank you so much for pointing this out.
This, and the comments about covariance/invariance, are intriguing, and I'll need to spend a lot more time reading through the RFC carefully to understand the details. There are clearly details of I don't have any specific requests for changes to the compiler, and my questions have been answered (thank you!), so I'll close this issue now. I appreciate everyone's help. |
This may simply be that I'm misunderstanding something. But I was surprised by the workaround necessary to make the following code work. When working on the Xorcism exercise in Exercism, I needed to return an
impl Iterator<Item=u8>
. This was complicated by the presence of two different lifetime parameters (the'a
parameter from the trait for thekey
field, which is a&'a [u8]
, and the'b
parameter for the&'b mut self
). With the following initial code:I got the error message:
However, if I replaced the line:
With the non-obvious and less intuitive:
The code compiled and ran as expected. I may be missing something, but I can't see a reason why borrowing the fields from the structure would be safe, but borrowing the structure itself would be dangerous.
Note that the original goal was to make
next_key
a method of theXorcism
struct, so that the best version of the code would read:Meta
rustc --version --verbose
:Also occurs on nightly:
The text was updated successfully, but these errors were encountered: