I am familiar with the rules of trait object lifetime bounds, and how they may be elided. This is not a question about how the language works, but rather if there’s a clever trick to get what I want. Consider the following two modules trying to do similar things:
pub mod a {
use std::sync::{Arc, Mutex};
pub struct Holder<T> {
// The Mutex exists for reasons that are out of scope.
// It is included just to clarify that `Holder<T>` is already invariant over `T`.
data: Arc<Mutex<T>>,
}
impl<T: Clone> Holder<T> {
pub fn constant(value: T) -> Self {
Holder { data: Arc::new(Mutex::new(value)) }
}
pub fn get(&self) -> T {
self.data.lock().unwrap().clone()
}
}
}
pub mod b {
use std::sync::Arc;
pub trait DataSource<T> {
fn get(&self) -> T;
}
pub struct Holder<T> {
data: Arc<dyn DataSource<T>>,
}
impl<T: Clone> Holder<T> {
pub fn constant(value: T) -> Self {
struct Constant<T>(T);
impl<T: Clone> DataSource<T> for Constant<T> {
fn get(&self) -> T {
self.0.clone()
}
}
Holder { data: Arc::new(Constant(value)) }
}
pub fn get(&self) -> T {
self.data.get()
}
}
}
These are intended to serve the same purposes (handles to data which may change over time, which allow reading that data at any point), except that b
uses a trait so that it can be extended to more kinds of data sources, whereas a
is fixed to one representation. However, b
does not compile:
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:39:28
|
39 | Holder { data: Arc::new(Constant(value)) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
31 | impl<T: Clone + 'static> Holder<T> {
| +++++++++
This error makes sense, but is there any way to solve it without changing the signature of Holder
? In particular, without adding a 'static
bound and without adding a lifetime parameter Holder<'a, T>
? What I would like is for the dyn DataSource
to somehow automatically get a lifetime filled in which is exactly T
’s validity (the intersection of T
’s contained lifetimes?), so that “T
always lives long enough”. Is there a way to persuade the type system to make that happen? I would really like to add the trait shown in b
while having an API surface otherwise identical to a
.