Skip to main content

diskann_utils/
lifetime.rs

1/*
2 * Copyright (c) Microsoft Corporation.
3 * Licensed under the MIT license.
4 */
5
6use std::{default::Default, marker::PhantomData};
7
8/// A utility `'static` compatible trait adding a lifetime to a type.
9pub trait WithLifetime: Send + Sync + 'static {
10    /// The associated type with a lifetime.
11    type Of<'a>: Send + Sync;
12}
13
14/// A [`WithLifetime`] annotator for `'static` types that discards the generic lifetime.
15///
16/// ```
17/// use diskann_utils::{WithLifetime, lifetime::Static};
18///
19/// fn foo<T: WithLifetime>(_: T::Of<'_>) {}
20///
21/// let x = f32::default();
22/// foo::<Static<f32>>(x);
23/// ```
24#[derive(Debug, Clone, Copy)]
25pub struct Static<T> {
26    _type: PhantomData<T>,
27}
28
29const _: () = assert!(std::mem::size_of::<Static<f32>>() == 0);
30
31impl<T> Static<T> {
32    /// Construct a new `Static` zero sized type.
33    pub const fn new() -> Self {
34        Self { _type: PhantomData }
35    }
36}
37
38impl<T> Default for Static<T> {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl<T> WithLifetime for Static<T>
45where
46    T: Send + Sync + 'static,
47{
48    type Of<'a> = T;
49}
50
51/// A [`WithLifetime`] annotator for slices.
52///
53/// ```
54/// use diskann_utils::{WithLifetime, lifetime::Slice};
55///
56/// fn foo<T: WithLifetime>(x: T::Of<'_>) {}
57///
58/// let v = vec![1usize, 2, 3];
59/// foo::<Slice<usize>>(&v);
60/// assert_eq!(v.len(), 3);
61/// ```
62#[derive(Debug, Clone, Copy)]
63pub struct Slice<T> {
64    _type: PhantomData<T>,
65}
66
67impl<T> Slice<T> {
68    pub const fn new() -> Self {
69        Self { _type: PhantomData }
70    }
71}
72
73impl<T> Default for Slice<T> {
74    fn default() -> Self {
75        Self::new()
76    }
77}
78
79impl<T> WithLifetime for Slice<T>
80where
81    T: Send + Sync + 'static,
82{
83    type Of<'a> = &'a [T];
84}
85
86///////////
87// Tests //
88///////////
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_static() {
96        fn foo<T>(x: T::Of<'_>) -> T::Of<'_>
97        where
98            T: WithLifetime,
99            for<'a> T::Of<'a>: 'static,
100        {
101            x
102        }
103
104        let x = f32::default();
105        assert_eq!(foo::<Static<f32>>(x), 0.0);
106
107        const _: Static<f32> = Static::new();
108
109        let _ = Static::<f32>::default();
110    }
111
112    #[test]
113    fn test_slice() {
114        fn foo<T>(x: T::Of<'_>) -> f32
115        where
116            T: for<'a> WithLifetime<Of<'a> = &'a [f32]>,
117        {
118            x.iter().sum()
119        }
120
121        let x = vec![1.0, 2.0, 3.0];
122        assert_eq!(foo::<Slice<f32>>(&x), 6.0);
123
124        const _: Slice<f32> = Slice::new();
125        let _ = Slice::<f32>::default();
126    }
127}