1use crate::trace::{Trace, Tracer};
2
3macro_rules! trace_acyclic {
23 ( <$( $g:ident ),*> $( $t: tt )* ) => {
24 impl<$( $g: 'static ),*> $crate::Trace for $($t)* {
25 #[inline]
26 fn is_type_tracked() -> bool where Self: Sized { false }
27 }
28 };
29 ( $( $t: ty ),* ) => {
30 $( trace_acyclic!(<> $t); )*
31 };
32}
33
34macro_rules! trace_fields {
53 ( $( $type:ty { $( $field:tt $(: $tp:ident )? ),* } )* ) => {
54 $(
55 impl< $( $( $tp: $crate::Trace )? ),* > $crate::Trace for $type {
56 fn trace(&self, tracer: &mut $crate::Tracer) {
57 let _ = tracer;
58 $( (&self . $field ).trace(tracer); )*
59 }
60 #[inline]
61 fn is_type_tracked() -> bool {
62 $( $( if $tp::is_type_tracked() { return true } )? )*
63 false
64 }
65 }
66 )*
67 };
68}
69
70trace_acyclic!(bool, char, f32, f64, i16, i32, i64, i8, isize, u16, u32, u64, u8, usize);
71trace_acyclic!(());
72trace_acyclic!(String, &'static str);
73
74mod tuples {
75 trace_fields!(
76 (A, B) { 0: A, 1: B }
77 (A, B, C) { 0: A, 1: B, 2: C }
78 (A, B, C, D) { 0: A, 1: B, 2: C, 3: D }
79 (A, B, C, D, E) { 0: A, 1: B, 2: C, 3: D, 4: E }
80 );
81}
82
83mod borrow {
84 use super::*;
85 use std::borrow::Cow;
86
87 impl<T: ToOwned + ?Sized> Trace for Cow<'static, T>
88 where
89 T::Owned: Trace,
90 {
91 fn trace(&self, tracer: &mut Tracer) {
92 match self {
93 Cow::Owned(v) => v.trace(tracer),
94 _ => (),
95 }
96 }
97
98 #[inline]
99 fn is_type_tracked() -> bool {
100 T::Owned::is_type_tracked()
101 }
102 }
103}
104
105mod boxed {
106 use super::*;
107
108 impl<T: Trace> Trace for Box<T> {
109 fn trace(&self, tracer: &mut Tracer) {
110 self.as_ref().trace(tracer);
111 }
112
113 #[inline]
114 fn is_type_tracked() -> bool {
115 T::is_type_tracked()
116 }
117 }
118
119 impl Trace for Box<dyn Trace> {
120 fn trace(&self, tracer: &mut Tracer) {
121 self.as_ref().trace(tracer);
122 }
123
124 #[inline]
125 fn is_type_tracked() -> bool {
126 true
128 }
129 }
130
131 impl Trace for Box<dyn Trace + Send> {
132 fn trace(&self, tracer: &mut Tracer) {
133 self.as_ref().trace(tracer);
134 }
135
136 #[inline]
137 fn is_type_tracked() -> bool {
138 true
139 }
140 }
141
142 impl Trace for Box<dyn Trace + Send + Sync> {
143 fn trace(&self, tracer: &mut Tracer) {
144 self.as_ref().trace(tracer);
145 }
146
147 #[inline]
148 fn is_type_tracked() -> bool {
149 true
150 }
151 }
152}
153
154mod cell {
155 use super::*;
156 use std::cell;
157
158 impl<T: Copy + Trace> Trace for cell::Cell<T> {
159 fn trace(&self, tracer: &mut Tracer) {
160 self.get().trace(tracer);
161 }
162
163 #[inline]
164 fn is_type_tracked() -> bool {
165 T::is_type_tracked()
166 }
167 }
168
169 impl<T: Trace> Trace for cell::RefCell<T> {
170 fn trace(&self, tracer: &mut Tracer) {
171 if let Ok(x) = self.try_borrow() {
177 x.trace(tracer);
178 }
179 }
180
181 #[inline]
182 fn is_type_tracked() -> bool {
183 T::is_type_tracked()
184 }
185 }
186}
187
188mod collections {
189 use super::*;
190 use std::collections;
191 use std::hash;
192
193 impl<K: Trace, V: Trace> Trace for collections::BTreeMap<K, V> {
194 fn trace(&self, tracer: &mut Tracer) {
195 for (k, v) in self {
196 k.trace(tracer);
197 v.trace(tracer);
198 }
199 }
200
201 #[inline]
202 fn is_type_tracked() -> bool {
203 K::is_type_tracked() || V::is_type_tracked()
204 }
205 }
206
207 impl<K: Eq + hash::Hash + Trace, V: Trace> Trace for collections::HashMap<K, V> {
208 fn trace(&self, tracer: &mut Tracer) {
209 for (k, v) in self {
210 k.trace(tracer);
211 v.trace(tracer);
212 }
213 }
214
215 #[inline]
216 fn is_type_tracked() -> bool {
217 K::is_type_tracked() || V::is_type_tracked()
218 }
219 }
220
221 impl<T: Trace> Trace for collections::LinkedList<T> {
222 fn trace(&self, tracer: &mut Tracer) {
223 for t in self {
224 t.trace(tracer);
225 }
226 }
227
228 #[inline]
229 fn is_type_tracked() -> bool {
230 T::is_type_tracked()
231 }
232 }
233
234 impl<T: Trace> Trace for collections::VecDeque<T> {
235 fn trace(&self, tracer: &mut Tracer) {
236 for t in self {
237 t.trace(tracer);
238 }
239 }
240
241 #[inline]
242 fn is_type_tracked() -> bool {
243 T::is_type_tracked()
244 }
245 }
246}
247
248mod vec {
249 use super::*;
250 impl<T: Trace> Trace for Vec<T> {
251 fn trace(&self, tracer: &mut Tracer) {
252 for t in self {
253 t.trace(tracer);
254 }
255 }
256
257 #[inline]
258 fn is_type_tracked() -> bool {
259 T::is_type_tracked()
260 }
261 }
262}
263
264#[allow(unknown_lints)]
266#[allow(coherence_leak_check)]
267mod func {
268 trace_acyclic!(<X> fn() -> X);
269
270 trace_acyclic!(<A, X> fn(&A) -> X);
271 trace_acyclic!(<A, X> fn(A) -> X);
272
273 trace_acyclic!(<A, B, X> fn(&A, &B) -> X);
274 trace_acyclic!(<A, B, X> fn(A, &B) -> X);
275 trace_acyclic!(<A, B, X> fn(&A, B) -> X);
276 trace_acyclic!(<A, B, X> fn(A, B) -> X);
277
278 trace_acyclic!(<A, B, C, X> fn(&A, &B, &C) -> X);
279 trace_acyclic!(<A, B, C, X> fn(A, &B, &C) -> X);
280 trace_acyclic!(<A, B, C, X> fn(&A, B, &C) -> X);
281 trace_acyclic!(<A, B, C, X> fn(A, B, &C) -> X);
282 trace_acyclic!(<A, B, C, X> fn(&A, &B, C) -> X);
283 trace_acyclic!(<A, B, C, X> fn(A, &B, C) -> X);
284 trace_acyclic!(<A, B, C, X> fn(&A, B, C) -> X);
285 trace_acyclic!(<A, B, C, X> fn(A, B, C) -> X);
286
287 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, &C, &D) -> X);
288 trace_acyclic!(<A, B, C, D, X> fn(A, &B, &C, &D) -> X);
289 trace_acyclic!(<A, B, C, D, X> fn(&A, B, &C, &D) -> X);
290 trace_acyclic!(<A, B, C, D, X> fn(A, B, &C, &D) -> X);
291 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, C, &D) -> X);
292 trace_acyclic!(<A, B, C, D, X> fn(A, &B, C, &D) -> X);
293 trace_acyclic!(<A, B, C, D, X> fn(&A, B, C, &D) -> X);
294 trace_acyclic!(<A, B, C, D, X> fn(A, B, C, &D) -> X);
295 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, &C, D) -> X);
296 trace_acyclic!(<A, B, C, D, X> fn(A, &B, &C, D) -> X);
297 trace_acyclic!(<A, B, C, D, X> fn(&A, B, &C, D) -> X);
298 trace_acyclic!(<A, B, C, D, X> fn(A, B, &C, D) -> X);
299 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, C, D) -> X);
300 trace_acyclic!(<A, B, C, D, X> fn(A, &B, C, D) -> X);
301 trace_acyclic!(<A, B, C, D, X> fn(&A, B, C, D) -> X);
302 trace_acyclic!(<A, B, C, D, X> fn(A, B, C, D) -> X);
303
304 trace_acyclic!(<A, B, C, D, E, X> fn(A, B, C, D, E) -> X);
305 trace_acyclic!(<A, B, C, D, E, F, X> fn(A, B, C, D, E, F) -> X);
306}
307
308mod ffi {
309 use std::ffi;
310
311 trace_acyclic!(ffi::CString, ffi::NulError, ffi::OsString);
312}
313
314mod net {
315 use std::net;
316
317 trace_acyclic!(
318 net::AddrParseError,
319 net::Ipv4Addr,
320 net::Ipv6Addr,
321 net::SocketAddrV4,
322 net::SocketAddrV6,
323 net::TcpListener,
324 net::TcpStream,
325 net::UdpSocket
326 );
327}
328
329mod option {
330 use super::*;
331
332 impl<T: Trace> Trace for Option<T> {
333 fn trace(&self, tracer: &mut Tracer) {
334 if let Some(ref t) = *self {
335 t.trace(tracer);
336 }
337 }
338
339 fn is_type_tracked() -> bool {
340 T::is_type_tracked()
341 }
342 }
343}
344
345mod path {
346 use std::path;
347
348 trace_acyclic!(path::PathBuf);
349}
350
351mod process {
352 use std::process;
353
354 trace_acyclic!(
355 process::Child,
356 process::ChildStderr,
357 process::ChildStdin,
358 process::ChildStdout,
359 process::Command,
360 process::ExitStatus,
361 process::Output,
362 process::Stdio
363 );
364}
365
366mod rc {
367 use std::rc;
368
369 trace_acyclic!(<T> rc::Rc<T>);
370 trace_acyclic!(<T> rc::Weak<T>);
371}
372
373mod result {
374 use super::*;
375
376 impl<T: Trace, U: Trace> Trace for Result<T, U> {
377 fn trace(&self, tracer: &mut Tracer) {
378 match *self {
379 Ok(ref t) => t.trace(tracer),
380 Err(ref u) => u.trace(tracer),
381 }
382 }
383
384 fn is_type_tracked() -> bool {
385 T::is_type_tracked() || U::is_type_tracked()
386 }
387 }
388}
389
390mod sync {
391 use super::*;
392 use std::sync;
393
394 trace_acyclic!(<T> sync::Arc<T>);
396
397 impl<T: Trace> Trace for sync::Mutex<T> {
398 fn trace(&self, tracer: &mut Tracer) {
399 if let Ok(x) = self.try_lock() {
413 x.trace(tracer);
414 }
415 }
416
417 #[inline]
418 fn is_type_tracked() -> bool {
419 T::is_type_tracked()
420 }
421 }
422
423 impl<T: Trace> Trace for sync::RwLock<T> {
424 fn trace(&self, tracer: &mut Tracer) {
425 if let Ok(x) = self.try_write() {
430 x.trace(tracer);
431 }
432 }
433
434 #[inline]
435 fn is_type_tracked() -> bool {
436 T::is_type_tracked()
437 }
438 }
439}
440
441mod thread {
442 use std::thread;
443
444 trace_acyclic!(<T> thread::JoinHandle<T>);
445 trace_acyclic!(<T> thread::LocalKey<T>);
446 trace_acyclic!(thread::Thread);
447}
448
449#[cfg(test)]
450mod tests {
451 use super::*;
452 use crate::Cc;
453 use std::cell::{Cell, RefCell};
454 use std::rc::Rc;
455
456 #[test]
457 fn test_is_type_tracked() {
458 assert!(!u8::is_type_tracked());
459 assert!(!<f32 as Trace>::is_type_tracked());
460 assert!(!String::is_type_tracked());
461 assert!(!Option::<u32>::is_type_tracked());
462 assert!(!Vec::<u8>::is_type_tracked());
463 assert!(!<(bool, f64)>::is_type_tracked());
464 assert!(!Cell::<u32>::is_type_tracked());
465 assert!(!RefCell::<String>::is_type_tracked());
466 assert!(Box::<dyn Trace>::is_type_tracked());
467 assert!(RefCell::<Box::<dyn Trace>>::is_type_tracked());
468 assert!(RefCell::<Vec::<Box::<dyn Trace>>>::is_type_tracked());
469 assert!(Vec::<RefCell::<Box::<dyn Trace>>>::is_type_tracked());
470 assert!(!Cc::<u8>::is_type_tracked());
471 assert!(!Vec::<Cc::<u8>>::is_type_tracked());
472
473 assert!(!<fn(u8) -> u8>::is_type_tracked());
474 assert!(!<fn(&u8) -> u8>::is_type_tracked());
475 }
476
477 #[test]
478 fn test_is_cyclic_type_tracked() {
479 type C1 = RefCell<Option<Rc<Box<S1>>>>;
480 struct S1(C1);
481 impl Trace for S1 {
482 fn trace(&self, t: &mut Tracer) {
483 self.0.trace(t);
484 }
485 fn is_type_tracked() -> bool {
486 C1::is_type_tracked()
488 }
489 }
490
491 type C2 = RefCell<Option<Cc<Box<S2>>>>;
492 struct S2(C2);
493 impl Trace for S2 {
494 fn trace(&self, t: &mut Tracer) {
495 self.0.trace(t);
496 }
497 fn is_type_tracked() -> bool {
498 true
500 }
501 }
502
503 assert!(!S1::is_type_tracked());
504 assert!(S2::is_type_tracked());
505 }
506}