1use std::borrow::{Borrow, BorrowMut};
2use std::ops::{Deref, DerefMut};
3
4use crate::Acyclic;
5use crate::trace::{Trace, Tracer};
6
7#[macro_export]
27macro_rules! trace_acyclic {
28 ( <$( $g:ident ),*> $( $t: tt )* ) => {
29 impl<$( $g: 'static + $crate::Acyclic ),*> $crate::Trace for $($t)* {
30 #[inline]
31 fn is_type_tracked() -> bool where Self: Sized { false }
32 }
33 unsafe impl<$( $g: 'static + $crate::Acyclic ),*> $crate::Acyclic for $($t)* {}
34 };
35 ( $( $t: ty ),* ) => {
36 $( trace_acyclic!(<> $t); )*
37 };
38}
39
40#[macro_export]
59macro_rules! trace_fields {
60 ( $( $type:ty { $( $field:tt $(: $tp:ident )? ),* } )* ) => {
61 $(
62 impl< $( $( $tp: $crate::Trace )? ),* > $crate::Trace for $type {
63 fn trace(&self, tracer: &mut $crate::Tracer) {
64 let _ = tracer;
65 $( (&self . $field ).trace(tracer); )*
66 }
67 #[inline]
68 fn is_type_tracked() -> bool {
69 $( $( if $tp::is_type_tracked() { return true } )? )*
70 false
71 }
72 }
73 unsafe impl< $( $( $tp: $crate::Acyclic )? ),* > $crate::Acyclic for $type {}
74 )*
75 };
76}
77
78trace_acyclic!(
79 bool, char, f32, f64, i16, i32, i64, i8, isize, u16, u32, u64, u8, usize
80);
81trace_acyclic!(());
82trace_acyclic!(String, &'static str);
83
84mod tuples {
85 trace_fields!(
86 (A,) { 0: A }
87 (A, B,) { 0: A, 1: B }
88 (A, B, C,) { 0: A, 1: B, 2: C }
89 (A, B, C, D,) { 0: A, 1: B, 2: C, 3: D }
90 (A, B, C, D, E,) { 0: A, 1: B, 2: C, 3: D, 4: E }
91 (A, B, C, D, E, F,) { 0: A, 1: B, 2: C, 3: D, 4: E, 5: F }
92 (A, B, C, D, E, F, G,) { 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G }
93 );
94}
95
96mod borrow {
97 use super::{Acyclic, Trace, Tracer};
98 use std::borrow::Cow;
99
100 impl<T: ToOwned + ?Sized> Trace for Cow<'static, T>
101 where
102 T::Owned: Trace,
103 {
104 fn trace(&self, tracer: &mut Tracer) {
105 if let Cow::Owned(v) = self {
106 v.trace(tracer);
107 }
108 }
109
110 #[inline]
111 fn is_type_tracked() -> bool {
112 T::Owned::is_type_tracked()
113 }
114 }
115 unsafe impl<T: ToOwned + ?Sized> Acyclic for Cow<'static, T> where T::Owned: Acyclic {}
116}
117
118mod boxed {
119 use super::{Acyclic, Trace, Tracer};
120 impl<T: Trace> Trace for Box<T> {
121 fn trace(&self, tracer: &mut Tracer) {
122 self.as_ref().trace(tracer);
123 }
124
125 #[inline]
126 fn is_type_tracked() -> bool {
127 T::is_type_tracked()
128 }
129 }
130 unsafe impl<T: Acyclic> Acyclic for Box<T> {}
131}
132
133mod cell {
134 use super::{Acyclic, Trace, Tracer};
135 use std::cell::{Cell, OnceCell, RefCell};
136
137 impl<T: Copy + Trace> Trace for Cell<T> {
138 fn trace(&self, tracer: &mut Tracer) {
139 self.get().trace(tracer);
140 }
141
142 #[inline]
143 fn is_type_tracked() -> bool {
144 T::is_type_tracked()
145 }
146 }
147 unsafe impl<T: Acyclic + Copy> Acyclic for Cell<T> {}
148
149 impl<T: Trace> Trace for RefCell<T> {
150 fn trace(&self, tracer: &mut Tracer) {
151 if let Ok(x) = self.try_borrow() {
157 x.trace(tracer);
158 }
159 }
160
161 #[inline]
162 fn is_type_tracked() -> bool {
163 T::is_type_tracked()
164 }
165 }
166 unsafe impl<T: Acyclic> Acyclic for RefCell<T> {}
167
168 impl<T: Trace> Trace for OnceCell<T> {
169 fn trace(&self, tracer: &mut Tracer) {
170 if let Some(x) = self.get() {
171 x.trace(tracer);
172 }
173 }
174
175 #[inline]
176 fn is_type_tracked() -> bool {
177 T::is_type_tracked()
178 }
179 }
180 unsafe impl<T: Acyclic> Acyclic for OnceCell<T> {}
181}
182
183#[cfg(feature = "im-rc")]
184mod im_collections {
185 use super::*;
186 use im_rc::{HashMap, HashSet, OrdMap, OrdSet, Vector};
187 impl<T: Trace + Clone> Trace for Vector<T> {
188 fn trace(&self, tracer: &mut Tracer) {
189 let _ = tracer;
190 for v in self.iter() {
191 v.trace(tracer);
192 }
193 }
194
195 fn is_type_tracked() -> bool
196 where
197 Self: Sized,
198 {
199 T::is_type_tracked()
200 }
201 }
202 impl<T: Trace + Clone, H: 'static> Trace for HashSet<T, H> {
203 fn trace(&self, tracer: &mut Tracer) {
204 let _ = tracer;
205 for v in self.iter() {
206 v.trace(tracer);
207 }
208 }
209
210 fn is_type_tracked() -> bool
211 where
212 Self: Sized,
213 {
214 T::is_type_tracked()
215 }
216 }
217 impl<T: Trace + Clone + Ord> Trace for OrdSet<T> {
218 fn trace(&self, tracer: &mut Tracer) {
219 let _ = tracer;
220 for v in self.iter() {
221 v.trace(tracer);
222 }
223 }
224
225 fn is_type_tracked() -> bool
226 where
227 Self: Sized,
228 {
229 T::is_type_tracked()
230 }
231 }
232 impl<K: Trace + Clone, V: Trace + Clone, H: 'static> Trace for HashMap<K, V, H> {
233 fn trace(&self, tracer: &mut Tracer) {
234 let _ = tracer;
235 for (k, v) in self.iter() {
236 k.trace(tracer);
237 v.trace(tracer);
238 }
239 }
240
241 fn is_type_tracked() -> bool
242 where
243 Self: Sized,
244 {
245 K::is_type_tracked() || V::is_type_tracked()
246 }
247 }
248 impl<K: Trace + Clone + Ord, V: Trace + Clone> Trace for OrdMap<K, V> {
249 fn trace(&self, tracer: &mut Tracer) {
250 let _ = tracer;
251 for (k, v) in self.iter() {
252 k.trace(tracer);
253 v.trace(tracer);
254 }
255 }
256
257 fn is_type_tracked() -> bool
258 where
259 Self: Sized,
260 {
261 K::is_type_tracked() || V::is_type_tracked()
262 }
263 }
264}
265
266mod collections {
267 use super::{Acyclic, Trace, Tracer};
268 use std::collections::{BTreeMap, HashMap, HashSet, LinkedList, VecDeque};
269 use std::hash::Hash;
270
271 impl<K: Trace, V: Trace> Trace for BTreeMap<K, V> {
272 fn trace(&self, tracer: &mut Tracer) {
273 for (k, v) in self {
274 k.trace(tracer);
275 v.trace(tracer);
276 }
277 }
278
279 #[inline]
280 fn is_type_tracked() -> bool {
281 K::is_type_tracked() || V::is_type_tracked()
282 }
283 }
284 unsafe impl<K: Acyclic, V: Acyclic> Acyclic for BTreeMap<K, V> {}
285
286 impl<K: Eq + Hash + Trace, H: 'static> Trace for HashSet<K, H> {
287 fn trace(&self, tracer: &mut Tracer) {
288 for k in self {
289 k.trace(tracer);
290 }
291 }
292
293 #[inline]
294 fn is_type_tracked() -> bool {
295 K::is_type_tracked()
296 }
297 }
298 unsafe impl<K: Acyclic + Hash + Eq, H: 'static> Acyclic for HashSet<K, H> {}
299
300 impl<K: Eq + Hash + Trace, V: Trace, H: 'static> Trace for HashMap<K, V, H> {
301 fn trace(&self, tracer: &mut Tracer) {
302 for (k, v) in self {
303 k.trace(tracer);
304 v.trace(tracer);
305 }
306 }
307
308 #[inline]
309 fn is_type_tracked() -> bool {
310 K::is_type_tracked() || V::is_type_tracked()
311 }
312 }
313 unsafe impl<K: Acyclic + Hash + Eq, V: Acyclic, H: 'static> Acyclic for HashMap<K, V, H> {}
314
315 impl<T: Trace> Trace for LinkedList<T> {
316 fn trace(&self, tracer: &mut Tracer) {
317 for t in self {
318 t.trace(tracer);
319 }
320 }
321
322 #[inline]
323 fn is_type_tracked() -> bool {
324 T::is_type_tracked()
325 }
326 }
327 unsafe impl<T: Acyclic> Acyclic for LinkedList<T> {}
328
329 impl<T: Trace> Trace for VecDeque<T> {
330 fn trace(&self, tracer: &mut Tracer) {
331 for t in self {
332 t.trace(tracer);
333 }
334 }
335
336 #[inline]
337 fn is_type_tracked() -> bool {
338 T::is_type_tracked()
339 }
340 }
341 unsafe impl<T: Acyclic> Acyclic for VecDeque<T> {}
342}
343
344mod rustc_hash {}
345
346mod vec {
347 use super::{Acyclic, Trace, Tracer};
348 impl<T: Trace> Trace for Vec<T> {
349 fn trace(&self, tracer: &mut Tracer) {
350 for t in self {
351 t.trace(tracer);
352 }
353 }
354
355 #[inline]
356 fn is_type_tracked() -> bool {
357 T::is_type_tracked()
358 }
359 }
360 unsafe impl<T: Acyclic> Acyclic for Vec<T> {}
361}
362
363mod slice {
364 use crate::{Acyclic, Trace, Tracer};
365
366 impl<T: Trace> Trace for [T] {
367 fn trace(&self, tracer: &mut Tracer) {
368 for t in self {
369 t.trace(tracer);
370 }
371 }
372 }
373 unsafe impl<T: Acyclic> Acyclic for [T] {}
374}
375
376#[allow(unknown_lints)]
378#[allow(coherence_leak_check)]
379mod func {
380 trace_acyclic!(<X> fn() -> X);
381
382 trace_acyclic!(<A, X> fn(&A) -> X);
383 trace_acyclic!(<A, X> fn(A) -> X);
384
385 trace_acyclic!(<A, B, X> fn(&A, &B) -> X);
386 trace_acyclic!(<A, B, X> fn(A, &B) -> X);
387 trace_acyclic!(<A, B, X> fn(&A, B) -> X);
388 trace_acyclic!(<A, B, X> fn(A, B) -> X);
389
390 trace_acyclic!(<A, B, C, X> fn(&A, &B, &C) -> X);
391 trace_acyclic!(<A, B, C, X> fn(A, &B, &C) -> X);
392 trace_acyclic!(<A, B, C, X> fn(&A, B, &C) -> X);
393 trace_acyclic!(<A, B, C, X> fn(A, B, &C) -> X);
394 trace_acyclic!(<A, B, C, X> fn(&A, &B, C) -> X);
395 trace_acyclic!(<A, B, C, X> fn(A, &B, C) -> X);
396 trace_acyclic!(<A, B, C, X> fn(&A, B, C) -> X);
397 trace_acyclic!(<A, B, C, X> fn(A, B, C) -> X);
398
399 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, &C, &D) -> X);
400 trace_acyclic!(<A, B, C, D, X> fn(A, &B, &C, &D) -> X);
401 trace_acyclic!(<A, B, C, D, X> fn(&A, B, &C, &D) -> X);
402 trace_acyclic!(<A, B, C, D, X> fn(A, B, &C, &D) -> X);
403 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, C, &D) -> X);
404 trace_acyclic!(<A, B, C, D, X> fn(A, &B, C, &D) -> X);
405 trace_acyclic!(<A, B, C, D, X> fn(&A, B, C, &D) -> X);
406 trace_acyclic!(<A, B, C, D, X> fn(A, B, C, &D) -> X);
407 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, &C, D) -> X);
408 trace_acyclic!(<A, B, C, D, X> fn(A, &B, &C, D) -> X);
409 trace_acyclic!(<A, B, C, D, X> fn(&A, B, &C, D) -> X);
410 trace_acyclic!(<A, B, C, D, X> fn(A, B, &C, D) -> X);
411 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, C, D) -> X);
412 trace_acyclic!(<A, B, C, D, X> fn(A, &B, C, D) -> X);
413 trace_acyclic!(<A, B, C, D, X> fn(&A, B, C, D) -> X);
414 trace_acyclic!(<A, B, C, D, X> fn(A, B, C, D) -> X);
415
416 trace_acyclic!(<A, B, C, D, E, X> fn(A, B, C, D, E) -> X);
417 trace_acyclic!(<A, B, C, D, E, F, X> fn(A, B, C, D, E, F) -> X);
418}
419
420mod ffi {
421 use std::ffi;
422
423 trace_acyclic!(ffi::CString, ffi::NulError, ffi::OsString);
424}
425
426mod net {
427 use std::net;
428
429 trace_acyclic!(
430 net::AddrParseError,
431 net::Ipv4Addr,
432 net::Ipv6Addr,
433 net::SocketAddrV4,
434 net::SocketAddrV6,
435 net::TcpListener,
436 net::TcpStream,
437 net::UdpSocket
438 );
439}
440
441mod option {
442 use super::{Acyclic, Trace, Tracer};
443
444 impl<T: Trace> Trace for Option<T> {
445 fn trace(&self, tracer: &mut Tracer) {
446 if let Some(ref t) = *self {
447 t.trace(tracer);
448 }
449 }
450
451 fn is_type_tracked() -> bool {
452 T::is_type_tracked()
453 }
454 }
455 unsafe impl<T: Acyclic> Acyclic for Option<T> {}
456}
457
458mod path {
459 use std::path;
460
461 trace_acyclic!(path::PathBuf);
462}
463
464mod process {
465 use std::process;
466
467 trace_acyclic!(
468 process::Child,
469 process::ChildStderr,
470 process::ChildStdin,
471 process::ChildStdout,
472 process::Command,
473 process::ExitStatus,
474 process::Output,
475 process::Stdio
476 );
477}
478
479mod rc {
480 use std::rc::{Rc, Weak};
481
482 use crate::Acyclic;
483
484 trace_acyclic!(<T> Rc<T> where T: Acyclic + ?Sized);
485 trace_acyclic!(<T> Weak<T>);
486}
487
488mod result {
489 use super::{Acyclic, Trace, Tracer};
490
491 impl<T: Trace, U: Trace> Trace for Result<T, U> {
492 fn trace(&self, tracer: &mut Tracer) {
493 match *self {
494 Ok(ref t) => t.trace(tracer),
495 Err(ref u) => u.trace(tracer),
496 }
497 }
498
499 fn is_type_tracked() -> bool {
500 T::is_type_tracked() || U::is_type_tracked()
501 }
502 }
503 unsafe impl<T: Acyclic, U: Acyclic> Acyclic for Result<T, U> {}
504}
505
506mod sync {
507 use super::{Trace, Tracer};
508 use std::sync;
509
510 trace_acyclic!(<T> sync::Arc<T>);
512
513 impl<T: Trace> Trace for sync::Mutex<T> {
514 fn trace(&self, tracer: &mut Tracer) {
515 if let Ok(x) = self.try_lock() {
529 x.trace(tracer);
530 }
531 }
532
533 #[inline]
534 fn is_type_tracked() -> bool {
535 T::is_type_tracked()
536 }
537 }
538
539 impl<T: Trace> Trace for sync::RwLock<T> {
540 fn trace(&self, tracer: &mut Tracer) {
541 if let Ok(x) = self.try_write() {
546 x.trace(tracer);
547 }
548 }
549
550 #[inline]
551 fn is_type_tracked() -> bool {
552 T::is_type_tracked()
553 }
554 }
555}
556
557mod thread {
558 use std::thread;
559
560 trace_acyclic!(<T> thread::JoinHandle<T>);
561 trace_acyclic!(<T> thread::LocalKey<T>);
562 trace_acyclic!(thread::Thread);
563}
564
565mod phantom {
566 use super::{Acyclic, Trace, Tracer};
567 use std::marker::PhantomData;
568 impl<T: 'static> Trace for PhantomData<T> {
569 fn trace(&self, _tracer: &mut Tracer) {}
570
571 #[inline]
572 fn is_type_tracked() -> bool {
573 false
574 }
575 }
576 unsafe impl<T: 'static> Acyclic for PhantomData<T> {}
577}
578
579#[cfg(test)]
580mod tests {
581 use super::*;
582 use crate::Cc;
583 use std::cell::{Cell, RefCell};
584
585 #[test]
586 fn test_is_type_tracked() {
587 assert!(!u8::is_type_tracked());
588 assert!(!<f32 as Trace>::is_type_tracked());
589 assert!(!String::is_type_tracked());
590 assert!(!Option::<u32>::is_type_tracked());
591 assert!(!Vec::<u8>::is_type_tracked());
592 assert!(!<(bool, f64)>::is_type_tracked());
593 assert!(!Cell::<u32>::is_type_tracked());
594 assert!(!RefCell::<String>::is_type_tracked());
595 assert!(TraceBox::<dyn Trace>::is_type_tracked());
596 assert!(RefCell::<TraceBox::<dyn Trace>>::is_type_tracked());
597 assert!(RefCell::<Vec::<TraceBox::<dyn Trace>>>::is_type_tracked());
598 assert!(Vec::<RefCell::<TraceBox::<dyn Trace>>>::is_type_tracked());
599 assert!(!Cc::<u8>::is_type_tracked());
600 assert!(!Vec::<Cc::<u8>>::is_type_tracked());
601
602 assert!(!<fn(u8) -> u8>::is_type_tracked());
603 assert!(!<fn(&u8) -> u8>::is_type_tracked());
604 }
605
606 #[test]
607 fn test_is_cyclic_type_tracked() {
608 type C2 = RefCell<Option<Cc<Box<S2>>>>;
609 struct S2(C2);
610 impl Trace for S2 {
611 fn trace(&self, t: &mut Tracer) {
612 self.0.trace(t);
613 }
614 fn is_type_tracked() -> bool {
615 true
617 }
618 }
619
620 assert!(S2::is_type_tracked());
621 }
622}
623
624#[derive(Debug, Clone)]
628pub struct TraceBox<T: ?Sized>(pub Box<T>);
629
630impl<T: ?Sized + Trace> Trace for TraceBox<T> {
631 fn trace(&self, tracer: &mut Tracer<'_>) {
632 self.0.trace(tracer);
633 }
634
635 fn is_type_tracked() -> bool {
636 true
637 }
638}
639unsafe impl<T: ?Sized> Acyclic for TraceBox<T> where T: Acyclic {}
640
641impl<T: ?Sized> From<Box<T>> for TraceBox<T> {
642 fn from(inner: Box<T>) -> Self {
643 Self(inner)
644 }
645}
646
647impl<T: ?Sized> Deref for TraceBox<T> {
648 type Target = T;
649
650 fn deref(&self) -> &Self::Target {
651 &self.0
652 }
653}
654impl<T: Trace + ?Sized> DerefMut for TraceBox<T> {
655 fn deref_mut(&mut self) -> &mut Self::Target {
656 &mut self.0
657 }
658}
659
660impl<T: ?Sized> Borrow<T> for TraceBox<T> {
661 fn borrow(&self) -> &T {
662 &self.0
663 }
664}
665
666impl<T: ?Sized> BorrowMut<T> for TraceBox<T> {
667 fn borrow_mut(&mut self) -> &mut T {
668 &mut self.0
669 }
670}
671
672impl<T: ?Sized> AsRef<T> for TraceBox<T> {
673 fn as_ref(&self) -> &T {
674 &self.0
675 }
676}
677
678impl<T: ?Sized> AsMut<T> for TraceBox<T> {
679 fn as_mut(&mut self) -> &mut T {
680 &mut self.0
681 }
682}