I have a struct with a lifetime:
struct HasLifetime<'a>( /* ... */ );
There is there is an implementation of the trait Foo
:
impl<'a, 'b: 'a> Foo for &'a mut HasLifetime<'b> { }
I want to implement the following function:
fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut Lifetime<'b>) -> impl Foo {
bar
}
This won't compile because the returned impl
is only valid for 'a
. However, specifying impl Foo + 'a
results in:
error[E0909]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> src/main.rs:7:60
|
7 | fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut HasLifetime<'b>) -> impl Trait + 'a {
| ^^^^^^^^^^^^^^^
|
note: hidden type `&'a mut HasLifetime<'b>` captures the lifetime 'b as defined on the function body at 7:1
--> src/main.rs:7:1
|
7 | fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut HasLifetime<'b>) -> impl Trait + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The seemingly equivalent function with a boxed trait object compiles:
fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut Lifetime<'b>) -> Box<Foo + 'a> {
Box::new(bar)
}
How can I define bar_to_foo
with impl Trait
?
Playground link
Lifetimes are what the Rust compiler uses to keep track of how long references are valid for. Checking references is one of the borrow checker's main responsibilities. Lifetimes help the borrow checker ensure that you never have invalid references.
Rust uses lifetime parameters to avoid such potential run-time errors. Since the compiler doesn't know in advance whether the if or the else block will execute, the code above won't compile and an error message will be printed that says, “a lifetime parameter is expected in compare 's signature.”
'_ , the anonymous lifetime Rust 2018 allows you to explicitly mark where a lifetime is elided, for types where this elision might otherwise be unclear. To do this, you can use the special lifetime '_ much like you can explicitly mark that a type is inferred with the syntax let x: _ = ..; .
Trait and lifetime bounds provide a way for generic items to restrict which types and lifetimes are used as their parameters. Bounds can be provided on any type in a where clause.
You need to indicate that the returned value is built upon multiple lifetimes. However, you can't use multiple lifetime bounds with impl Trait
, and attempting to do so doesn't have a useful error message.
There's a trick you can use that involves creating a dummy trait that has a lifetime parameter:
trait Captures<'a> {}
impl<'a, T: ?Sized> Captures<'a> for T {}
fn bar_to_foo<'a, 'b: 'a>(bar: &'a mut HasLifetime<'b>) -> impl Trait + Captures<'b> + 'a {
bar
}
Thankfully, this only occurs when the "hidden" lifetime is invariant, which occurs because the reference is mutable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With