`format!` requires static lifetime? - rust

Here is a minimal reproducible sample:
use std::fmt::{self, Debug, Formatter};
pub trait Apple {}
impl Debug for dyn Apple {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("Apple")
}
}
struct Basket<'a> {
apples: Vec<Box<dyn Apple + 'a>>,
}
impl<'a> Basket<'a> {
fn f(&self) {
let x = format!("{:?}", self.apples);
}
}
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/lib.rs:17:17
|
17 | let x = format!("{:?}", self.apples);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 15:6...
--> src/lib.rs:15:6
|
15 | impl<'a> Basket<'a> {
| ^^
note: ...so that the types are compatible
--> src/lib.rs:17:17
|
17 | let x = format!("{:?}", self.apples);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `(&std::vec::Vec<std::boxed::Box<dyn Apple>>,)`
found `(&std::vec::Vec<std::boxed::Box<(dyn Apple + 'a)>>,)`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
--> src/lib.rs:17:33
|
17 | let x = format!("{:?}", self.apples);
| ^^^^^^^^^^^
= note: expected `std::fmt::Debug`
found `std::fmt::Debug`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
format! should only borrow self.apples for a very short period of time (only borrow during its formatting process). However, it even requires self.apples to have the 'static lifetime.
EDIT: Now I see why is that, after kind help from comments and other answers. According to #Shepmaster's suggestion, I move this part of content into an answer.

Because of default trait object lifetimes, impl Debug for dyn Apple is shorthand for impl Debug for dyn Apple + 'static.
To write an implementation for non-'static trait objects, you can override this default lifetime with an explicit one:
impl<'a> Debug for dyn Apple + 'a

I see the reason after #chuigda_whitegive 's "non-reproducible" sample:
This is wrong
pub trait Apple {}
impl Debug for dyn Apple {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("Apple")
}
}
but should do this
pub trait Apple: Debug {}
I still do not understand, why I should not impl Debug for dyn Apple. It compiles in other cases and it sounds reasonable ("when debugging, we should output the Apple string").
EDIT
Now I see how to do a two-letter modification to the original question. One more anonymous lifetime and this compiles:
use std::fmt::{Debug, Formatter};
pub trait Apple {}
impl Debug for dyn Apple + '_ {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("Apple")
}
}
struct Basket<'a> {
apples: Vec<Box<dyn Apple + 'a>>,
}
impl<'a> Basket<'a> {
fn f(&self) {
let x = format!("{:?}", self.apples);
}
}
For why this is the case, please see #Matt Brubeck 's answer.

Related

Trait associated type lifetime and self

I have a struct that wraps a std::cell::Ref and provides access by reference to the underlying value. Something like this:
use std::cell::Ref;
struct IntAccess<'a> {
i: Ref<'a, i32>,
}
impl IntAccess<'_> {
fn get(&self) -> &i32 {
&self.i
}
}
This works fine. Since I have multiple structs like this, I'd like to define a common trait:
trait Access {
type Item;
fn get(&self) -> Self::Item;
}
However, I get into trouble when trying to implement Access for IntAccess:
impl<'a> Access for IntAccess<'a> {
type Item = &'a i32;
fn get(&self) -> Self::Item {
&self.i
}
}
It fails with the following error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:23:9
|
23 | &self.i
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:22:12
|
22 | fn get(&self) -> Self::Item {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:23:9
|
23 | &self.i
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:19:6
|
19 | impl<'a> Access for IntAccess<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:22:33
|
22 | fn get(&self) -> Self::Item {
| _________________________________^
23 | | &self.i
24 | | }
| |_____^
= note: expected `<IntAccess<'a> as Access>`
found `<IntAccess<'_> as Access>`
I think I kind of get what the compiler is trying to tell me: I'm trying to borrow self.i which has an anonymous lifetime unrelated to the lifetime of Self::Item ('a). So what seems to be needed is to somehow tie the lifetime of self in get to the lifetime 'a. Is there a way to do this?
I have to admit that I don't fully grasp the problem. Since I pass the lifetime 'a to the Ref, and Ref internally stores a reference with this lifetime, it seems to me that it should somehow be possible to get a reference with lifetime 'a out of it without having to explicitly tie self to this lifetime as well. So what am I missing here?
Your understanding is correct. About your doubt, let's name the lifetimes for easier debugging:
impl<'a> Access for IntAccess<'a> {
type Item = &'a i32;
fn get<'b>(&'b self) -> Self::Item {
&self.i
}
}
self has the type &'b IntAccess<'a>. 'b is shorter than or equal to 'a - that is required for self to be well-formed, i.e. able to exist (otherwise, it would contain a dangling reference).
For that reason, we cannot borrow self for more than 'b - or we could do something like:
let v: IntAccess<'a>;
let inner: &'a i32 = {
let r: &'b IntAccess<'a> = &v;
<IntAccess<'a> as Access>::get(r)
}
let mut_r: &mut IntAccess<'a> = &mut v;
And we have both a shared and a mutable reference to (parts of) inner!
Your problem cannot be solved fully without Generic Associated Types. They allow you to parameterize an associated type by a lifetime, making it able to express "I want to return this associated type tied to the lifetime of self":
#![feature(generic_associated_types)]
trait Access {
type Item<'a>
where
Self: 'a;
fn get<'a>(&'a self) -> Self::Item<'a>;
// Or, with lifetime elision:
// fn get(&self) -> Self::Item<'_>;
}
impl<'a> Access for IntAccess<'a> {
type Item<'b> = &'b i32
where
'a: 'b;
fn get<'b>(&'b self) -> Self::Item<'b> {
&self.i
}
}
Playground.
Can we do that on stable? We can emulate that. Instead of implementing Access for IntAccess itself, we will implement it for a reference to it!
trait Access {
type Item;
fn get(self) -> Self::Item;
}
impl<'a, 'b> Access for &'b IntAccess<'a> {
type Item = &'b i32;
fn get(self) -> &'b i32 {
&self.i
}
}
Playground
This does not always work, and thus is not a full replacement to GATs, but is good enough in this case.

understanding e0507 error and trying to resolve

I am in a &mut self function, I have a member field that is a Vec<u8>. I want to call a windows xxxA function (via the excellent winapi crate). I have no choice on the fn signature, it is implementing a trait.
I think I need to make a CString. So I tried
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
this doesn't work.
error[E0507]: cannot move out of `self.buf` which is behind a mutable reference
--> src\windbg.rs:51:36
|
51 | let str = CString::new(self.buf).unwrap();
| ^^^^^^^^ move occurs because `self.buf` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait
I've read the explain of this but none of the 3 suggested solutions seem possible.
Here is the whole struct:
struct WinDbgWriter {
buf: Vec<u8>,
}
use std::io::Write;
impl std::io::Write for WinDbgWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.buf.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
}
If we take your minimized case and try to borrow self.mut to avoid moving it (transferring its ownership), we get a new error which has a suggestion:
error[E0277]: the trait bound `Vec<u8>: From<&Vec<u8>>` is not satisfied
--> src/lib.rs:9:33
|
9 | let _str = CString::new(&self.buf).unwrap();
| ^^^^^^^^^
| |
| the trait `From<&Vec<u8>>` is not implemented for `Vec<u8>`
| help: consider adding dereference here: `&*self.buf`
|
= help: the following implementations were found:
<Vec<T> as From<&[T]>>
<Vec<T> as From<&mut [T]>>
<Vec<T> as From<BinaryHeap<T>>>
<Vec<T> as From<Box<[T]>>>
and 6 others
= note: required because of the requirements on the impl of `Into<Vec<u8>>` for `&Vec<u8>`
If we follow that suggestion, or explicitly coerce self.buf to a &[u8], then the code compiles.
CString::new takes an argument of some type Into<Vec<u8>>, but self.buf is, at this point of type &Vec<u8> because of it being accessed through a &self borrow, and there's no impl Into<Vec<u8>> for &Vec<u8>.

cannot infer an appropriate lifetime for lifetime parameter with multiple references with the same lifetime inside a struct [E0495]

I had gotten an error in my code about lifetime inferrence, and I have been able to reduce the code to the following:
use std::collections::HashMap;
struct A<'a> {
x: &'a mut HashMap<&'a str, i32>,
}
impl<'a> A<'a> {
fn new(x: &'a mut HashMap<&'a str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
The error that results from this is
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:13:17
|
13 | let a = A::new(self.x);
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src/main.rs:12:5
|
12 | / fn test(&mut self) {
13 | | let a = A::new(self.x);
14 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 7:6...
--> src/main.rs:7:6
|
7 | impl<'a> A<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
= note: expected `&mut std::collections::HashMap<&str, i32>`
found `&mut std::collections::HashMap<&'a str, i32>`
I do not understand what is the error in this case, but I did find that if I add a lifetime 'b to struct A, such that the str reference in the HashMap has a lifetime of 'b, the codes does compile. Here is how the code looks like after the aforementioned change:
use std::collections::HashMap;
struct A<'a, 'b> {
x: &'a mut HashMap<&'b str, i32>,
}
impl<'a, 'b> A<'a, 'b> {
fn new(x: &'a mut HashMap<&'b str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
However, I have no idea why that change works. To my understanding, having both lifetimes be 'a means that A must live as long as the HashMap, and the HashMap must live as long as the &strs that are used as its keys, which I see no issue with. I also do not see how the change adds any additional information for the compiler. Can anyone please shed some light for me on this situation?
Change the A::test() function into
fn test(&'a mut self) { // Add lifetime specification
let a = A::new(self.x);
}
and it should work.
The compiler said it cannot infer lifetime for A::new(), and the first note mentioned "anonymous lifetime", that means the compiler doesn't know the lifetime of self.x in A::new(self.x). So we just need to tell the compiler that self has a lifetime of 'a.

Why is a reference to a type that implements Fn not recognized as a callable?

Even if &T is defined as implementing the Fn trait, the compiler rejects it when invoking it is as a callable:
trait Trait {
fn act(self);
}
//passes
fn test_ref_input_as_trait<'a, T>(t: &'a T)
where
&'a T: Trait,
{
t.act();
}
//fails
fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
where
&'a T: Fn(),
{
t();
}
//passes
fn test_input_as_fntrait<T>(t: T)
where
T: Fn(),
{
t();
}
The compiler rejects the definition of the second function with:
error[E0618]: expected function, found `&'a T`
--> src/lib.rs:18:5
|
14 | fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
| - `&'a T` defined here
...
18 | t();
| ^^^ not a function
With nightly (1.32), the error message is replaced with:
error[E0618]: expected function, found `&'a T`
--> src/lib.rs:18:5
|
14 | fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
| - `&'a T` defined here
...
18 | t();
| ^--
| |
| call expression requires function
Maybe I'm missing something, but why is the compiler accepting the definition but not allowing it to be invoked? Is it a syntactical shortcoming from my side that leads it to understand something else?
There is an open issue (#42736) about this. However, the docs for Fn state:
for any type F that implements Fn, &F implements Fn, too.
This means that the following works:
fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
where
T: Fn(),
{
t();
}
This is perhaps a bug (e.g. it works if you replace the &'a T by (&'a T,)). Nevertheless, you can call the function like this:
fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
where
&'a T: Fn(),
{
(&t)();
}
but since T: Fn() automatically implies &T: Fn(), it is easier and more idiomatic to just write like your last example.
fn test_ref_input_as_fntrait<F: Fn()>(t: F) {
t();
}
fn main() {
test_ref_input_as_fntrait(&|| println!("it's okay!"));
}

Fn as trait concrete lifetime required

I want to use an API that I can modify reg:
struct Ctx;
trait Foo {}
trait Ex {
fn do_<'a>(&self, cx: &'a mut Ctx) -> Box<Foo + 'a>;
}
impl<F> Ex for F
where
F: for<'a> Fn(&'a mut Ctx) -> Box<Foo + 'a>,
{
fn do_<'a>(&self, ecx: &'a mut Ctx) -> Box<Foo + 'a> {
(*self)(ecx)
}
}
fn reg<F>(name: &str, ext: F)
where
F: Ex + 'static,
{
}
//My code starts here
struct Boo;
impl Boo {
fn f1<'a>(&self, cx: &'a mut Ctx) -> Box<Foo + 'a> {
unimplemented!();
}
}
fn main() {
let boo = Boo;
reg("aaa", move |cx| boo.f1(cx));
}
But I got an error:
error[E0271]: type mismatch resolving `for<'a> <[closure#src/main.rs:33:16: 33:36 boo:_] as std::ops::FnOnce<(&'a mut Ctx,)>>::Output == std::boxed::Box<Foo + 'a>`
--> src/main.rs:33:5
|
33 | reg("aaa", move |cx| boo.f1(cx));
| ^^^ expected bound lifetime parameter 'a, found concrete lifetime
|
= note: concrete lifetime that was found is lifetime '_#9r
= note: required because of the requirements on the impl of `Ex` for `[closure#src/main.rs:33:16: 33:36 boo:_]`
= note: required by `reg`
error[E0281]: type mismatch: `[closure#src/main.rs:33:16: 33:36 boo:_]` implements the trait `std::ops::Fn<(&mut Ctx,)>`, but the trait `for<'a> std::ops::Fn<(&'a mut Ctx,)>` is required
--> src/main.rs:33:5
|
33 | reg("aaa", move |cx| boo.f1(cx));
| ^^^ -------------------- implements `std::ops::Fn<(&mut Ctx,)>`
| |
| requires `for<'a> std::ops::Fn<(&'a mut Ctx,)>`
| expected concrete lifetime, found bound lifetime parameter 'a
|
= note: required because of the requirements on the impl of `Ex` for `[closure#src/main.rs:33:16: 33:36 boo:_]`
= note: required by `reg`
How can I fix this?
In real code my struct Boo contains some data,
and want to call reg for it twice, so I not implement trait Ex, but
try to use closure.
Looks like issue #38714.
While it is being fixed, you can directly implement Ex for Boo.
impl Ex for Boo {
fn do_<'a>(&self, ecx: &'a mut Ctx) -> Box<Foo + 'a> {
self.f1(ecx)
}
}
fn main() {
let boo = Boo;
reg("aaa", boo);
}
In real code my struct Boo contains some data, and want to call reg for it twice, so I not implement trait Ex, but try to use closure.
You'll not be able to do that with the code you provided. move |cx| boo.f1(cx) moves boo into the closure, and you can't use boo after that.
If you want to share data, you'll need to use Rc in Boo.

Resources