# `::fix_hidden_lifetime_bug`
[![Repository](https://img.shields.io/badge/repository-GitHub-brightgreen.svg)](
https://github.com/danielhenrymantilla/fix_hidden_lifetime_bug.rs)
[![Latest version](https://img.shields.io/crates/v/fix-hidden-lifetime-bug.svg)](
https://crates.io/crates/fix-hidden-lifetime-bug)
[![Documentation](https://docs.rs/fix-hidden-lifetime-bug/badge.svg)](
https://docs.rs/fix-hidden-lifetime-bug)
[![MSRV](https://img.shields.io/badge/MSRV-1.65.0-white)](
https://gist.github.com/danielhenrymantilla/8e5b721b3929084562f8f65668920c33)
[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](
https://github.com/rust-secure-code/safety-dance/)
[![License](https://img.shields.io/crates/l/fix-hidden-lifetime-bug.svg)](
https://github.com/danielhenrymantilla/fix_hidden_lifetime_bug.rs/blob/master/LICENSE-ZLIB)
[![CI](https://github.com/danielhenrymantilla/fix_hidden_lifetime_bug.rs/workflows/CI/badge.svg)](
https://github.com/danielhenrymantilla/fix_hidden_lifetime_bug.rs/actions)
### Are you getting one of the following errors (E700)?
- ```rust,ignore
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> examples/main.rs:13:40
|
13 | fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
| ^^^^^^^^^^^^^^^
|
note: hidden type `&'a mut &'b ()` captures the lifetime `'b` as defined on the function body at 13:12
--> examples/main.rs:13:12
|
13 | fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
| ^^
```
Problematic code
```rust,compile_fail
fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
it
}
```
- ```rust,ignore
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> examples/main.rs:8:45
|
8 | async fn bar<'a> (_: &(), _: Box) {
| ^
|
note: hidden type `impl Future` captures lifetime smaller than the function body
--> examples/main.rs:8:45
|
8 | async fn bar<'a> (_: &(), _: Box) {
| ^
```
Problematic code
```rust ,ignore
async fn bar<'a> (_: &(), _: Box) {
/* … */
}
```
EDIT: Fixed as of 1.69.0
- ```rust,ignore
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> examples/main.rs:4:57
|
4 | async fn baz<'a>(a: &'static (), b: &(), c: &()) {
| ^
|
note: hidden type `impl Future` captures lifetime smaller than the function body
--> examples/main.rs:4:57
|
4 | async fn baz<'a>(a: &'static (), b: &(), c: &()) {
| ^
```
Problematic code
```rust ,ignore
async fn baz<'a>(a: &'static (), b: &(), c: &()) {
/* … */
}
```
EDIT: Fixed as of 1.69.0
Then you can add the attribute provided by this crate to automagically generate
an equivalent signature that soothes such a grumpy compiler 🙃
- See [the lifetime bug `async` issue], as well as [this other comment](
https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999) for
more info.
The fix is thus to perform the unsugaring from an `async fn` to an `fn`
yielding a `Future`, and then just adding the necessary `+ Captures<'_>`
bounds.
- See also [this post](
https://users.rust-lang.org/t/lifetimes-in-smol-executor/59157/8?u=yandros)
where I explain the issue more in detail.
[the lifetime bug `async` issue]: https://github.com/rust-lang/rust/issues/63033
### Usage
1. `cargo add fix_hidden_lifetime_bug`, or add the following to your `Cargo.toml` file:
```toml
[dependencies]
fix-hidden-lifetime-bug = "x.y.z"
```
- where you can find the version using `cargo search fix_hidden_lifetime_bug`
1. Add the following to your `lib.rs` file:
```rust,ignore
#[macro_use]
extern crate fix_hidden_lifetime_bug;
```
1. Slap a `#[fix_hidden_lifetime_bug]` on the problematic function:
```rust,ignore
#[fix_hidden_lifetime_bug] // <-- Add this!
fn foo<'a, 'b>(it: &'a mut &'b ()) -> impl 'a + Sized {
it
}
```
```rust,ignore
#[fix_hidden_lifetime_bug] // <-- Add this!
async fn baz<'a>(fst: &'static str, snd: &str, thrd: &str) {
/* … */
}
```
### Extra features
- #### Full support for methods
In the case of methods, the `Self` type may be hiding lifetime parameters on
its own, in which case a macro annotation on the method alone may not have
enough syntactical information to generate the fix:
```rust,compile_fail
use ::fix_hidden_lifetime_bug::fix_hidden_lifetime_bug;
struct Invariant<'lt> (
fn(&()) -> &mut &'lt (),
);
impl Invariant<'_> {
#[fix_hidden_lifetime_bug]
fn quux(&self) -> impl '_ + Sized { self }
}
```
In that case, the fix is to also decorate the whole `impl` block with
the attribute:
```rust
use ::fix_hidden_lifetime_bug::fix_hidden_lifetime_bug;
struct Invariant<'lt> (
fn(&()) -> &mut &'lt (),
);
#[fix_hidden_lifetime_bug]
impl Invariant<'_> {
#[fix_hidden_lifetime_bug]
fn quux(&self) -> impl '_ + Sized { self }
}
```
___
- #### Displaying the expansions
By enabling the `"showme"` Cargo feature:
```toml
[dependencies]
fix-hidden-lifetime-bug.version = "x.y.z"
fix-hidden-lifetime-bug.features = ["showme"]
```
you can then feed a `showme` parameter to specific
`#[fix_hidden_lifetime_bug]` annotations, as follows:
```rust,ignore
#[fix_hidden_lifetime_bug(showme)]
```
Example
```rust,ignore
use ::fix_hidden_lifetime_bug::fix_hidden_lifetime_bug;
#[fix_hidden_lifetime_bug(showme)]
async fn baz<'a>(a: &'static (), b: &'_ (), c: &'_ ()) {
println!("Hello, World!");
}
```
outputs:
```rust
fn baz<'a, '_0, '_1, '__async_fut>(
a: &'static (),
b: &'_0 (),
c: &'_1 (),
) -> impl '__async_fut
+ ::fix_hidden_lifetime_bug::core::future::Future
This will make the attribute display the result of its expansion (and
its expansion only! Hence yielding output that is way more readable than
that from `cargo expand` or other such tools), basically showing you how to
manually fix a given function signature if you so wish (_e.g._, to avoid
depending on proc-macro processing _every_ time the annotated function is
compiled, or to make the life easier for IDEs).
Should you fix the signature, you may then be interested in:
- ### Opting out of the magic proc-macro attribute
If you don't want to have to recompile each time the proc-macro able to fix
function signatures for you (_e.g._, you rather want it to [show you how to
fix the signature] so that you can do it through exclusive usage of
`+ Captures<'…>` additions), so as not to have to pay the proc-macro
compilation time each time you compile from scratch, then you can opt out of
it by disabling the `default-features` of the crate: this will disable the
`proc-macros` features, which is the one that brings it to the table.
That way, you can still use this then very lightweight crate just for its
`Captures<'…>` (and maybe `MentionsTy<…>`) definitions, and the
documentation that goes with it!
```toml
[dependencies]
…
fix-hidden-lifetime-bug.version = "x.y.z"
fix-hidden-lifetime-bug.default-features = false
```
[show you how to fix the signature]: #displaying-the-expansions