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