Reputation: 1637
Consider next function for example:
fn print(input: &dyn Display) {
println!("{}", input);
}
It works fine, as intended.
Now consider a little bit more complex example using trait with the same function inside:
trait Print {
type Input: ?Sized;
fn print(input: &Self::Input);
}
impl Print for f64 {
type Input = dyn Display;
// actually the same function as before
fn print(input: &dyn Display) {
println!("{}", input);
}
}
Now if I modify first function like this:
fn print(input: &dyn Display) {
f64::print(input);
}
I got compile error:
error[E0759]: `input` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
Why is this happening? I see no reason for 'static
lifetime requirement in trait's associated type.
Worked example here.
Upvotes: 1
Views: 64
Reputation: 27208
Yes, when a dyn _
type is used as an associated type, it implicitly receives a lifetime bound of 'static
. This is to prevent situations like this:
pub trait Stew {
type Item: ?Sized;
fn stew(&mut self, item: Box<Self::Item>);
}
use std::fmt::Display;
pub struct DisplayStew(Vec<Box<dyn Display>>);
impl Stew for DisplayStew {
type Item = dyn Display;
fn stew(&mut self, item: Box<Self::Item>) {
self.0.push(item);
}
}
impl DisplayStew {
pub fn new() -> Self {
DisplayStew(Vec::new())
}
pub fn look(&self) {
for item in &self.0 {
println!("- {}", item);
}
}
}
fn main() {
let mut bowl = DisplayStew::new();
bowl.stew(Box::new(123.456));
bowl.stew(Box::new("abcdef"));
{ // 'a begins
let s = "foo".to_owned();
bowl.stew(Box::new(&s)); // Box<&'a str>
} // 'a expires
// s was borrowed by bowl, but has ceased to exist, what now?
bowl.look();
}
Without a lifetime parameter, the compiler has no way of restricting how long a type may keep a reference to its associated type.
On stable Rust (1.58.1), there is currently no way to address this, but the following version works on unstable:
#![feature(generic_associated_types)]
use std::fmt::Display;
trait Print {
type Input<'a>: ?Sized;
fn print<'a>(input: &'a Self::Input<'a>);
}
impl Print for f64 {
type Input<'a> = dyn Display + 'a;
fn print<'a>(input: &'a (dyn Display + 'a)) {
println!("{}", input);
}
}
fn print(input: &dyn Display) {
println!("{}", input);
f64::print(input);
}
fn main() {
print(&123.);
}
Upvotes: 3