Missing lifetimes needed in impl
item don't have enough help for newcomer devs #135589
Description
If you write like
impl IntoIterator for &S {
type Item = &T;
type IntoIter = std::collections::btree_map::Values<i32, T>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
--> src/main.rs:5:17
|
5 | type Item = &T;
| ^ this lifetime must come from the implemented type
error[E0106]: missing lifetime specifier
--> src/main.rs:6:56
|
6 | type IntoIter = std::collections::btree_map::Values<i32, T>;
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
6 | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>;
| ++++ +++
ignoring the first one for now, if you follow the suggestion you get
error[E0195]: lifetime parameters or bounds on type `IntoIter` do not match the trait declaration
--> src/main.rs:6:18
|
6 | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>;
| ^^^^ lifetimes do not match type in trait
Both of these cases should instead mention likely adding the lifetime to the impl
if either the trait or the self type have any lifetimes, named or anon. We should mention that the <'a>
should be removed to match the def, and point at the def if local to modify it to add it to the trait.
If we don't add the <'a>
to the type IntoIter
, we get something closer to what we want:
error[E0261]: use of undeclared lifetime name `'a`
--> src/main.rs:6:57
|
6 | type IntoIter = std::collections::btree_map::Values<'a, i32, T>;
| ^^ undeclared lifetime
|
help: consider introducing lifetime `'a` here
|
6 | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>;
| ++++
help: consider introducing lifetime `'a` here
|
4 | impl<'a> IntoIterator for &S {
| ++++
We shouldn't be suggesting modifying type IntoIter
if we can know that the trait definition didn't have named lifetimes.
If we add impl<'a>
, then we get a very terse output:
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/main.rs:4:6
|
4 | impl<'a> IntoIterator for &S {
| ^^ unconstrained lifetime parameter
This should look at the trait and self type and see if there is any anon lifetime at play, and suggest using the named lifetime there. In this case, &'a S
.
In all of these cases we still get:
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
--> src/main.rs:5:17
|
5 | type Item = &T;
| ^ this lifetime must come from the implemented type
When impl
has lifetimes, the above should suggest using that lifetime.
Currently the documentation of E0261
mentions a similar enough case, but E0207
doesn't. We'd likely want to add a mention about lifetimes in the latter.
Inspired by mainmatter/100-exercises-to-learn-rust#245
- on
type NoLt = TypeMissingLt;
, do not suggesttype NoLt<'a> = TypeMisingLt<'a>;
if the trait doesn't accept it - on
type NoLt = TypeMissingLt;
, suggest adding a lifetime to theimpl
if the trait or self type have anon lifetimes - on
type NoLt<'a> = TypeMissingLt<'a>;
, suggest removing the lifetime from thetype
if theimpl
has a named lifetime - on
type NoLt = TypeMissingLt<'a>;
, suggest adding'a
to theimpl
if the trait or self type have anon lifetimes - on
impl<'a> IntoIterator for &S
, suggest changing the self type to&'a S
- on
type NoLt = &T;
, ifimpl
has a lifetime suggest using that - on
type NoLt = &T;
, suggest using a named lifetime from theimpl
if present - on
type NoLt = &T;
, suggest adding'a
to theimpl
if the trait or self type have anon lifetimes - expand the documentation of
E0207
to mention these cases