Attribute Macro comemo_macros::track
source · #[track]
Expand description
Make a type trackable.
This attribute can be applied to an inherent implementation block or trait
definition. It implements the Track
trait for the type or trait object.
§Tracking immutably and mutably
This allows you to
-
call
track()
on that type, producing aTracked<T>
container. Used as an argument to a memoized function, these containers enjoy fine-grained access tracking instead of blunt hashing. -
call
track_mut()
on that type, producing aTrackedMut<T>
. For mutable arguments, tracking is the only option, so that comemo can replay the side effects when there is a cache hit.
If you attempt to track any mutable methods, your type must implement
Clone
so that comemo can roll back attempted mutations which did not
result in a cache hit.
§Restrictions
Tracked impl blocks or traits may not be generic and may only contain methods. Just like with memoized functions, certain restrictions apply to tracked methods:
-
The only obversable impurity tracked methods may exhibit are mutations through
&mut self
. Comemo stops you from using basic mutable arguments and return values, but it cannot determine all sources of impurity, so this is your responsibility. Tracked methods also must not return mutable references or other types which allow untracked mutation. You are allowed to use interior mutability if it is not observable (even in immutable methods, as long as they stay idempotent). -
The return values of tracked methods must implement
Hash
and must feed all the information they expose to the hasher. Otherwise, memoized results might get reused invalidly. -
The arguments to a tracked method must be
Send
andSync
because they are stored in the global cache.
Furthermore:
- Tracked methods cannot be generic.
- They cannot be
unsafe
,async
orconst
. - They must take an
&self
or&mut self
parameter. - Their arguments must implement
ToOwned
. - Their return values must implement
Hash
. - They cannot use destructuring patterns in their arguments.
§Example
/// File storage.
struct Files(HashMap<PathBuf, String>);
#[comemo::track]
impl Files {
/// Load a file from storage.
fn read(&self, path: &str) -> String {
self.0.get(Path::new(path)).cloned().unwrap_or_default()
}
}
impl Files {
/// Write a file to storage.
fn write(&mut self, path: &str, text: &str) {
self.0.insert(path.into(), text.into());
}
}