Skip to content
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

Tweak output of missing lifetime on associated type #135602

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

estebank
Copy link
Contributor

Each commit can be reviewed independently. Address parts of #135589.


When an associated type is missing a lifetime, point at its enclosing impl, whether it has or doesn't have lifetimes defined. If it does have a lifetime, suggest using it.

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
  --> $DIR/missing-lifetime-in-assoc-type-1.rs:8:17
   |
LL | impl<'a> IntoIterator for &S {
   |     ---- there is a named lifetime specified on the impl block you could use
...
LL |     type Item = &T;
   |                 ^ this lifetime must come from the implemented type
   |
help: consider using the lifetime from the impl block
   |
LL |     type Item = &'a T;
   |                  ++
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
  --> $DIR/missing-lifetime-in-assoc-type-2.rs:5:17
   |
LL | impl IntoIterator for &S {
   |     - you could add a lifetime on the impl block, if the trait or the self type can have one
LL |     type Item = &T;
   |                 ^ this lifetime must come from the implemented type

On unconstrained lifetime on impl block, suggest using it if there's an implicit borrow in the self type

error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
  --> $DIR/missing-lifetime-in-assoc-type-1.rs:4:6
   |
LL | impl<'a> IntoIterator for &S {
   |      ^^ unconstrained lifetime parameter
   |
help: consider using the named lifetime here instead of an implict lifetime
   |
LL | impl<'a> IntoIterator for &'a S {
   |                            ++

Do not suggest introducing lifetime in impl assoc type


Previously we only showed the trait's assoc item if the trait was local, because we were looking for a small span only for the generics, which we don't have for foreign traits. We now use def_span for the item, so we at least provide some context, even if its span is too wide.

error[E0195]: lifetime parameters or bounds on type `IntoIter` do not match the trait declaration
   --> tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs:7:18
    |
7   |     type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>;
    |                  ^^^^ lifetimes do not match type in trait
    |
   ::: /home/gh-estebank/rust/library/core/src/iter/traits/collect.rs:292:5
    |
292 |     type IntoIter: Iterator<Item = Self::Item>;
    |     ------------------------------------------ lifetimes in impl do not match this type in trait

@rustbot
Copy link
Collaborator

rustbot commented Jan 16, 2025

r? @Nadrieril

rustbot has assigned @Nadrieril.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 16, 2025
@rust-log-analyzer

This comment has been minimized.

When an associated type is missing a lifetime, point at its enclosing `impl`, whether it has or doesn't have lifetimes defined. If it does have a lifetime, suggest using it.

```
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
  --> $DIR/missing-lifetime-in-assoc-type-1.rs:8:17
   |
LL | impl<'a> IntoIterator for &S {
   |     ---- there is a named lifetime specified on the impl block you could use
...
LL |     type Item = &T;
   |                 ^ this lifetime must come from the implemented type
   |
help: consider using the lifetime from the impl block
   |
LL |     type Item = &'a T;
   |                  ++
```

```
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
  --> $DIR/missing-lifetime-in-assoc-type-2.rs:5:17
   |
LL | impl IntoIterator for &S {
   |     - you could add a lifetime on the impl block, if the trait or the self type can have one
LL |     type Item = &T;
   |                 ^ this lifetime must come from the implemented type
```
…s an implicit borrow in the self type

```
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
  --> $DIR/missing-lifetime-in-assoc-type-1.rs:4:6
   |
LL | impl<'a> IntoIterator for &S {
   |      ^^ unconstrained lifetime parameter
   |
help: consider using the named lifetime here instead of an implict lifetime
   |
LL | impl<'a> IntoIterator for &'a S {
   |                            ++
```
```
error[E0261]: use of undeclared lifetime name `'a`
  --> $DIR/missing-lifetime-in-assoc-type-2.rs:7:57
   |
LL | impl IntoIterator for &S {
   |     - help: consider introducing lifetime `'a` here: `<'a>`
...
LL |     type IntoIter = std::collections::btree_map::Values<'a, i32, T>;
   |                                                         ^^ undeclared lifetime
```

```
error[E0106]: missing lifetime specifier
  --> $DIR/issue-74918-missing-lifetime.rs:9:30
   |
LL |     type Item = IteratorChunk<T, S>;
   |                              ^ expected named lifetime parameter
   |
help: consider introducing a named lifetime parameter
   |
LL ~ impl<'a, T, S: Iterator<Item = T>> Iterator for ChunkingIterator<T, S> {
LL ~     type Item = IteratorChunk<'a, T, S>;
   |
```
Previously we only showed the trait's assoc item if the trait was local, because we were looking for a small span only for the generics, which we don't have for foreign traits. We now use `def_span` for the item, so we at least provide some context, even if its span is too wide.

```
error[E0195]: lifetime parameters or bounds on type `IntoIter` do not match the trait declaration
   --> tests/ui/lifetimes/missing-lifetime-in-assoc-type-4.rs:7:18
    |
7   |     type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>;
    |                  ^^^^ lifetimes do not match type in trait
    |
   ::: /home/gh-estebank/rust/library/core/src/iter/traits/collect.rs:292:5
    |
292 |     type IntoIter: Iterator<Item = Self::Item>;
    |     ------------------------------------------ lifetimes in impl do not match this type in trait
```
Given an associated item that needs a named lifetime, look at the enclosing `impl` item for one. If there is none, look at the self type and the implemented trait to see if either of those has an anonimous lifetime. If so, suggest adding a named lifetime.

```
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
  --> $DIR/missing-lifetime-in-assoc-type-2.rs:5:17
   |
LL |     type Item = &T;
   |                 ^ this lifetime must come from the implemented type
   |
help: add a lifetime to the impl block and use it in the self type and associated type
   |
LL ~ impl<'a> IntoIterator for &'a S {
LL ~     type Item = &'a T;
   |
```
Move the previous long message to a note and use a shorter primary message:

```
error: missing lifetime in associated type
  --> $DIR/missing-lifetime-in-assoc-type-1.rs:9:17
   |
LL | impl<'a> IntoIterator for &S {
   |     ---- there is a named lifetime specified on the impl block you could use
...
LL |     type Item = &T;
   |                 ^ this lifetime must come from the implemented type
   |
note: in the trait the associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
help: consider using the lifetime from the impl block
   |
LL |     type Item = &'a T;
   |                  ++
```
Copy link
Contributor Author

@estebank estebank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attached screenshots as I find that 1) the colors help get a better sense of what the output looks in practice and 2) the lack of spans into the std types makes it harder to get what I was going for.

Comment on lines +17 to +26
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> $DIR/missing-lifetime-in-assoc-type-1.rs:4:6
|
LL | impl<'a> IntoIterator for &S {
| ^^ unconstrained lifetime parameter
|
help: consider using the named lifetime here instead of an implict lifetime
|
LL | impl<'a> IntoIterator for &'a S {
| ++
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +1 to +13
error: missing lifetime in associated type
--> $DIR/missing-lifetime-in-assoc-type-4.rs:5:17
|
LL | type Item = &T;
| ^ this lifetime must come from the implemented type
|
note: in the trait the associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
help: add a lifetime to the impl block and use it in the self type and associated type
|
LL ~ impl<'a> IntoIterator for &'a S {
LL ~ type Item = &'a T;
|
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 15 to 22
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/missing-lifetime-in-assoc-type-2.rs:7:57
|
LL | impl IntoIterator for &S {
| - help: consider introducing lifetime `'a` here: `<'a>`
...
LL | type IntoIter = std::collections::btree_map::Values<'a, i32, T>;
| ^^ undeclared lifetime
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@estebank
Copy link
Contributor Author

Feel free to review on a per-commit basis and stop early. I can split-off later commits onto their own PRs. They are all together because they end up affecting the same output and build on each other, but they don't need to land together.

@rustbot rustbot added the WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) label Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants