Skip to main content

burn_core/module/param/
constant.rs

1use alloc::format;
2use burn_tensor::kind::{Autodiff, Basic};
3use core::fmt::Display;
4
5use crate as burn;
6use crate::module::{
7    AutodiffModule, Content, Devices, Module, ModuleDisplay, ModuleDisplayDefault, ModuleMapper,
8    ModuleVisitor,
9};
10use burn_tensor::{Device, Tensor};
11
12/// Constant macro.
13#[macro_export]
14macro_rules! empty {
15    (module) => {
16        fn visit<V: burn::module::ModuleVisitor>(&self, _visitor: &mut V) {
17            // Nothing to do
18        }
19
20        fn map<M: burn::module::ModuleMapper>(self, _mapper: &mut M) -> Self {
21            self
22        }
23
24        fn to_device(self, _: &burn::tensor::Device) -> Self {
25            self
26        }
27
28        fn fork(self, _: &burn::tensor::Device) -> Self {
29            self
30        }
31
32        fn collect_devices(&self, devices: burn::module::Devices) -> burn::module::Devices {
33            devices
34        }
35    };
36
37    (ad_module, $type:ty) => {
38        fn valid(&self) -> Self {
39            self.clone()
40        }
41
42        fn from_inner(module: Self) -> Self {
43            module
44        }
45    };
46
47    ($type:ty) => {
48        impl burn::module::Module for $type {
49            empty!(module);
50        }
51
52        impl burn::module::AutodiffModule for $type {
53            empty!(ad_module, $type);
54        }
55
56        impl burn::module::ModuleDisplayDefault for $type {
57            fn content(&self, content: burn::module::Content) -> Option<burn::module::Content> {
58                let string = format!("{}", self);
59                content.add_formatted(&string).optional()
60            }
61        }
62
63        impl burn::module::ModuleDisplay for $type {}
64    };
65}
66
67// TODO: breaking change for these constant types (currently empty record, non-persistent)?
68
69// General Types
70empty!(alloc::string::String);
71empty!(bool);
72
73// Float Types
74empty!(f64);
75empty!(f32);
76empty!(half::bf16);
77empty!(half::f16);
78
79// Unsigned Integer Types
80empty!(usize);
81empty!(u64);
82empty!(u32);
83empty!(u16);
84empty!(u8);
85
86// Signed Integer Types
87empty!(isize);
88empty!(i64);
89empty!(i32);
90empty!(i16);
91empty!(i8);
92
93impl burn::module::ModuleDisplay for str {}
94impl burn::module::ModuleDisplayDefault for str {
95    fn content(&self, content: burn::module::Content) -> Option<burn::module::Content> {
96        content.add_formatted(&self).optional()
97    }
98}
99
100// TODO: tensor record should persist
101impl<const D: usize, K: Basic> Module for Tensor<D, K> {
102    fn visit<V: ModuleVisitor>(&self, _visitor: &mut V) {}
103
104    fn map<M: ModuleMapper>(self, _mapper: &mut M) -> Self {
105        self
106    }
107
108    fn to_device(self, device: &Device) -> Self {
109        self.to_device(device)
110    }
111
112    fn fork(self, device: &Device) -> Self {
113        self.to_device(device)
114    }
115
116    fn collect_devices(&self, mut devices: Devices) -> Devices {
117        let device = self.device();
118
119        if !devices.contains(&device) {
120            devices.push(device)
121        }
122
123        devices
124    }
125}
126
127impl<const D: usize, K: Basic> ModuleDisplayDefault for Tensor<D, K> {
128    fn content(&self, content: Content) -> Option<Content> {
129        let string = format!("Tensor {{rank: {D}, shape: {:?}}}", self.shape().as_slice());
130        content.add_single(&string).optional()
131    }
132}
133
134impl<const D: usize, K: Basic> ModuleDisplay for Tensor<D, K> {}
135
136impl<const D: usize, K: Autodiff> AutodiffModule for Tensor<D, K> {
137    fn valid(&self) -> Self {
138        self.clone().inner()
139    }
140
141    fn from_inner(tensor: Self) -> Self {
142        Tensor::from_inner(tensor)
143    }
144}
145
146// TODO: no longer necessary?
147// impl<T> Module for PhantomData<T> {
148//     type Record = EmptyRecord;
149
150//     fn visit<V: ModuleVisitor>(&self, _visitor: &mut V) {
151//         // Nothing to do
152//     }
153
154//     fn map<M: ModuleMapper>(self, _mapper: &mut M) -> Self {
155//         self
156//     }
157
158//     fn load_record(self, _record: Self::Record) -> Self {
159//         self
160//     }
161
162//     fn into_record(self) -> Self::Record {
163//         EmptyRecord::new()
164//     }
165
166//     fn to_device(self, _: &Device) -> Self {
167//         self
168//     }
169
170//     fn fork(self, _: &Device) -> Self {
171//         self
172//     }
173
174//     fn collect_devices(&self, devices: Devices) -> Devices {
175//         devices
176//     }
177// }
178
179// impl<T> ModuleDisplayDefault for PhantomData<T> {
180//     fn content(&self, content: Content) -> Option<Content> {
181//         content.add_single(&"PhantomData".to_string()).optional()
182//     }
183// }
184
185// impl<T> ModuleDisplay for PhantomData<T> {}
186
187// impl<T> AutodiffModule for PhantomData<T> {
188//     fn valid(&self) -> Self {
189//         PhantomData
190//     }
191
192//     fn from_inner(_module: Self) -> Self {
193//         Self
194//     }
195// }
196
197/// Container to satisfy the Module trait for types that are not modules.
198#[derive(Clone, Debug)]
199#[deprecated(
200    since = "0.21.0",
201    note = "Ignored<T> is deprecated. Use #[module(skip)] for non-persistent fields (same behavior)."
202)]
203pub struct Ignored<T>(pub T);
204
205#[allow(deprecated)]
206impl<T> Module for Ignored<T>
207where
208    T: Sync + Send + core::fmt::Debug + Clone,
209{
210    fn visit<V: ModuleVisitor>(&self, _visitor: &mut V) {
211        // Nothing to do
212    }
213
214    fn map<M: ModuleMapper>(self, _mapper: &mut M) -> Self {
215        self
216    }
217
218    fn to_device(self, _: &Device) -> Self {
219        self
220    }
221
222    fn fork(self, _: &Device) -> Self {
223        self
224    }
225
226    fn collect_devices(&self, devices: Devices) -> Devices {
227        devices
228    }
229}
230
231#[allow(deprecated)]
232impl<T> ModuleDisplayDefault for Ignored<T>
233where
234    T: Sync + Send + core::fmt::Debug + Clone,
235{
236    fn content(&self, content: Content) -> Option<Content> {
237        // For now, just print the debug representation of the ignored value
238        content.add_single(&format!("{:?}", self.0)).optional()
239    }
240}
241
242#[allow(deprecated)]
243impl<T> ModuleDisplay for Ignored<T> where T: Sync + Send + core::fmt::Debug + Clone {}
244
245#[allow(deprecated)]
246impl<T> Display for Ignored<T>
247where
248    T: Sync + Send + core::fmt::Debug + Clone,
249{
250    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
251        write!(f, "{:?}", self.0)
252    }
253}
254
255#[allow(deprecated)]
256impl<T> AutodiffModule for Ignored<T>
257where
258    T: Sync + Send + core::fmt::Debug + Clone,
259{
260    fn valid(&self) -> Self {
261        self.clone()
262    }
263
264    fn from_inner(module: Self) -> Self {
265        module
266    }
267}
268
269#[allow(deprecated)]
270// Implement deref for Ignored
271impl<T> core::ops::Deref for Ignored<T> {
272    type Target = T;
273
274    fn deref(&self) -> &Self::Target {
275        &self.0
276    }
277}
278
279#[cfg(all(test, feature = "std"))]
280mod tests {
281    use core::marker::PhantomData;
282
283    use burn::module::Module;
284
285    use crate as burn;
286
287    #[test]
288    fn empty_module_with_phantom() {
289        #[derive(Module, Debug, new)]
290        struct EmptyModule<T: core::fmt::Debug + Clone + Send> {
291            #[module(skip)]
292            _phantom: PhantomData<T>,
293        }
294
295        let _module = EmptyModule::<bool>::new();
296
297        assert_eq!(core::mem::size_of::<EmptyModule<bool>>(), 0);
298    }
299}