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

Conflicting error messages for HRTB in impl Trait #69112

Open
JustAPerson opened this issue Feb 12, 2020 · 1 comment
Open

Conflicting error messages for HRTB in impl Trait #69112

JustAPerson opened this issue Feb 12, 2020 · 1 comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@JustAPerson
Copy link
Contributor

JustAPerson commented Feb 12, 2020

Rust declares the lifetime 'a is both undeclared and that it is a shadowing declaration

#[derive(Debug)]
struct Ctx<'d> {
    phantom: std::marker::PhantomData<&'d ()>   
}
fn map<'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
    data.into_iter().inspect(|t| println!("{:?}", ctx))
}

My more complicated example is trying to use the &'c mut Ctx<'d> reference in one of the closures passed to Iterator::map() so I need to somehow incorporate the lifetime 'c into the return type.

Instead I get this confusing error:

error[E0261]: use of undeclared lifetime name `'a`
 --> src/lib.rs:5:95
  |
5 | fn map<'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
  |                                                                                               ^^ undeclared lifetime

error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
 --> src/lib.rs:5:69
  |
5 | fn map<'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
  |                                                                     ^^                        -- first declared here
  |                                                                     |
  |                                                                     lifetime 'a already in scope

error[E0261]: use of undeclared lifetime name `'a`
 --> src/lib.rs:5:108
  |
5 | fn map<'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
  |                                                                                                            ^^ undeclared lifetime

error: aborting due to 3 previous errors

You'll notice the help text of the first error says "undeclared lifetime" but the help of the second says "first declared here" and then gives a bogus "already in scope" hint.

@JustAPerson JustAPerson added the C-bug Category: This is a bug. label Feb 12, 2020
@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. A-lifetimes Area: Lifetimes / regions C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. and removed C-bug Category: This is a bug. C-enhancement Category: An issue proposing an enhancement or a PR with one. labels Feb 12, 2020
@estebank
Copy link
Contributor

Current output:

error[E0261]: use of undeclared lifetime name `'a`
 --> src/lib.rs:6:108
  |
6 | fn map<'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
  |        - help: consider introducing lifetime `'a` here: `'a,`                                              ^^ undeclared lifetime

error[E0261]: use of undeclared lifetime name `'a`
 --> src/lib.rs:6:95
  |
6 | fn map<'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
  |        - help: consider introducing lifetime `'a` here: `'a,`                                 ^^ undeclared lifetime

After applying suggestion:

error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
 --> src/lib.rs:6:73
  |
6 | fn map<'a, 'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
  |        -- first declared here                                           ^^ lifetime `'a` already in scope

error[E0700]: hidden type for `impl Iterator<Item = ()> + 'a` captures lifetime that does not appear in bounds
 --> src/lib.rs:7:5
  |
6 | fn map<'a, 'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a where 'c: 'a {
  |                --                                              ------------------------------------- opaque type defined here
  |                |
  |                hidden type `Inspect<std::vec::IntoIter<()>, {closure@src/lib.rs:7:30: 7:33}>` captures the lifetime `'d` as defined here
7 |     data.into_iter().inspect(|t| println!("{:?}", ctx))
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
help: to declare that `impl Iterator<Item = ()> + 'a` captures `'d`, you can add an explicit `'d` lifetime bound
  |
6 | fn map<'a, 'c, 'd: 'c>(ctx: &'c mut Ctx<'d>, data: Vec<()>) -> impl for<'a> Iterator<Item = ()> + 'a + 'd where 'c: 'a {
  |                                                                                                      ++++

error[E0373]: closure may outlive the current function, but it borrows `ctx`, which is owned by the current function
 --> src/lib.rs:7:30
  |
7 |     data.into_iter().inspect(|t| println!("{:?}", ctx))
  |                              ^^^                  --- `ctx` is borrowed here
  |                              |
  |                              may outlive borrowed value `ctx`
  |
note: closure is returned here
 --> src/lib.rs:7:5
  |
7 |     data.into_iter().inspect(|t| println!("{:?}", ctx))
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `ctx` (and any other referenced variables), use the `move` keyword
  |
7 |     data.into_iter().inspect(move |t| println!("{:?}", ctx))
  |                              ++++

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants