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::*;
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::*;
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::*;
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
183mod collections {
184 use super::*;
185 use std::collections::{BTreeMap, HashMap, HashSet, LinkedList, VecDeque};
186 use std::hash::Hash;
187
188 impl<K: Trace, V: Trace> Trace for BTreeMap<K, V> {
189 fn trace(&self, tracer: &mut Tracer) {
190 for (k, v) in self {
191 k.trace(tracer);
192 v.trace(tracer);
193 }
194 }
195
196 #[inline]
197 fn is_type_tracked() -> bool {
198 K::is_type_tracked() || V::is_type_tracked()
199 }
200 }
201 unsafe impl<K: Acyclic, V: Acyclic> Acyclic for BTreeMap<K, V> {}
202
203 impl<K: Eq + Hash + Trace, H: 'static> Trace for HashSet<K, H> {
204 fn trace(&self, tracer: &mut Tracer) {
205 for k in self {
206 k.trace(tracer);
207 }
208 }
209
210 #[inline]
211 fn is_type_tracked() -> bool {
212 K::is_type_tracked()
213 }
214 }
215 unsafe impl<K: Acyclic + Hash + Eq, H: 'static> Acyclic for HashSet<K, H> {}
216
217 impl<K: Eq + Hash + Trace, V: Trace, H: 'static> Trace for HashMap<K, V, H> {
218 fn trace(&self, tracer: &mut Tracer) {
219 for (k, v) in self {
220 k.trace(tracer);
221 v.trace(tracer);
222 }
223 }
224
225 #[inline]
226 fn is_type_tracked() -> bool {
227 K::is_type_tracked() || V::is_type_tracked()
228 }
229 }
230 unsafe impl<K: Acyclic + Hash + Eq, V: Acyclic, H: 'static> Acyclic for HashMap<K, V, H> {}
231
232 impl<T: Trace> Trace for LinkedList<T> {
233 fn trace(&self, tracer: &mut Tracer) {
234 for t in self {
235 t.trace(tracer);
236 }
237 }
238
239 #[inline]
240 fn is_type_tracked() -> bool {
241 T::is_type_tracked()
242 }
243 }
244 unsafe impl<T: Acyclic> Acyclic for LinkedList<T> {}
245
246 impl<T: Trace> Trace for VecDeque<T> {
247 fn trace(&self, tracer: &mut Tracer) {
248 for t in self {
249 t.trace(tracer);
250 }
251 }
252
253 #[inline]
254 fn is_type_tracked() -> bool {
255 T::is_type_tracked()
256 }
257 }
258 unsafe impl<T: Acyclic> Acyclic for VecDeque<T> {}
259}
260
261mod rustc_hash {}
262
263mod vec {
264 use super::*;
265 impl<T: Trace> Trace for Vec<T> {
266 fn trace(&self, tracer: &mut Tracer) {
267 for t in self {
268 t.trace(tracer);
269 }
270 }
271
272 #[inline]
273 fn is_type_tracked() -> bool {
274 T::is_type_tracked()
275 }
276 }
277 unsafe impl<T: Acyclic> Acyclic for Vec<T> {}
278}
279
280mod slice {
281 use crate::{Acyclic, Trace, Tracer};
282
283 impl<T: Trace> Trace for [T] {
284 fn trace(&self, tracer: &mut Tracer) {
285 for t in self {
286 t.trace(tracer);
287 }
288 }
289 }
290 unsafe impl<T: Acyclic> Acyclic for [T] {}
291}
292
293#[allow(unknown_lints)]
295#[allow(coherence_leak_check)]
296mod func {
297 trace_acyclic!(<X> fn() -> X);
298
299 trace_acyclic!(<A, X> fn(&A) -> X);
300 trace_acyclic!(<A, X> fn(A) -> X);
301
302 trace_acyclic!(<A, B, X> fn(&A, &B) -> X);
303 trace_acyclic!(<A, B, X> fn(A, &B) -> X);
304 trace_acyclic!(<A, B, X> fn(&A, B) -> X);
305 trace_acyclic!(<A, B, X> fn(A, B) -> X);
306
307 trace_acyclic!(<A, B, C, X> fn(&A, &B, &C) -> X);
308 trace_acyclic!(<A, B, C, X> fn(A, &B, &C) -> X);
309 trace_acyclic!(<A, B, C, X> fn(&A, B, &C) -> X);
310 trace_acyclic!(<A, B, C, X> fn(A, B, &C) -> X);
311 trace_acyclic!(<A, B, C, X> fn(&A, &B, C) -> X);
312 trace_acyclic!(<A, B, C, X> fn(A, &B, C) -> X);
313 trace_acyclic!(<A, B, C, X> fn(&A, B, C) -> X);
314 trace_acyclic!(<A, B, C, X> fn(A, B, C) -> X);
315
316 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, &C, &D) -> X);
317 trace_acyclic!(<A, B, C, D, X> fn(A, &B, &C, &D) -> X);
318 trace_acyclic!(<A, B, C, D, X> fn(&A, B, &C, &D) -> X);
319 trace_acyclic!(<A, B, C, D, X> fn(A, B, &C, &D) -> X);
320 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, C, &D) -> X);
321 trace_acyclic!(<A, B, C, D, X> fn(A, &B, C, &D) -> X);
322 trace_acyclic!(<A, B, C, D, X> fn(&A, B, C, &D) -> X);
323 trace_acyclic!(<A, B, C, D, X> fn(A, B, C, &D) -> X);
324 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, &C, D) -> X);
325 trace_acyclic!(<A, B, C, D, X> fn(A, &B, &C, D) -> X);
326 trace_acyclic!(<A, B, C, D, X> fn(&A, B, &C, D) -> X);
327 trace_acyclic!(<A, B, C, D, X> fn(A, B, &C, D) -> X);
328 trace_acyclic!(<A, B, C, D, X> fn(&A, &B, C, D) -> X);
329 trace_acyclic!(<A, B, C, D, X> fn(A, &B, C, D) -> X);
330 trace_acyclic!(<A, B, C, D, X> fn(&A, B, C, D) -> X);
331 trace_acyclic!(<A, B, C, D, X> fn(A, B, C, D) -> X);
332
333 trace_acyclic!(<A, B, C, D, E, X> fn(A, B, C, D, E) -> X);
334 trace_acyclic!(<A, B, C, D, E, F, X> fn(A, B, C, D, E, F) -> X);
335}
336
337mod ffi {
338 use std::ffi;
339
340 trace_acyclic!(ffi::CString, ffi::NulError, ffi::OsString);
341}
342
343mod net {
344 use std::net;
345
346 trace_acyclic!(
347 net::AddrParseError,
348 net::Ipv4Addr,
349 net::Ipv6Addr,
350 net::SocketAddrV4,
351 net::SocketAddrV6,
352 net::TcpListener,
353 net::TcpStream,
354 net::UdpSocket
355 );
356}
357
358mod option {
359 use super::*;
360
361 impl<T: Trace> Trace for Option<T> {
362 fn trace(&self, tracer: &mut Tracer) {
363 if let Some(ref t) = *self {
364 t.trace(tracer);
365 }
366 }
367
368 fn is_type_tracked() -> bool {
369 T::is_type_tracked()
370 }
371 }
372 unsafe impl<T: Acyclic> Acyclic for Option<T> {}
373}
374
375mod path {
376 use std::path;
377
378 trace_acyclic!(path::PathBuf);
379}
380
381mod process {
382 use std::process;
383
384 trace_acyclic!(
385 process::Child,
386 process::ChildStderr,
387 process::ChildStdin,
388 process::ChildStdout,
389 process::Command,
390 process::ExitStatus,
391 process::Output,
392 process::Stdio
393 );
394}
395
396mod rc {
397 use std::rc::{Rc, Weak};
398
399 use crate::Acyclic;
400
401 trace_acyclic!(<T> Rc<T> where T: Acyclic + ?Sized);
402 trace_acyclic!(<T> Weak<T>);
403}
404
405mod result {
406 use super::*;
407
408 impl<T: Trace, U: Trace> Trace for Result<T, U> {
409 fn trace(&self, tracer: &mut Tracer) {
410 match *self {
411 Ok(ref t) => t.trace(tracer),
412 Err(ref u) => u.trace(tracer),
413 }
414 }
415
416 fn is_type_tracked() -> bool {
417 T::is_type_tracked() || U::is_type_tracked()
418 }
419 }
420 unsafe impl<T: Acyclic, U: Acyclic> Acyclic for Result<T, U> {}
421}
422
423mod sync {
424 use super::*;
425 use std::sync;
426
427 trace_acyclic!(<T> sync::Arc<T>);
429
430 impl<T: Trace> Trace for sync::Mutex<T> {
431 fn trace(&self, tracer: &mut Tracer) {
432 if let Ok(x) = self.try_lock() {
446 x.trace(tracer);
447 }
448 }
449
450 #[inline]
451 fn is_type_tracked() -> bool {
452 T::is_type_tracked()
453 }
454 }
455
456 impl<T: Trace> Trace for sync::RwLock<T> {
457 fn trace(&self, tracer: &mut Tracer) {
458 if let Ok(x) = self.try_write() {
463 x.trace(tracer);
464 }
465 }
466
467 #[inline]
468 fn is_type_tracked() -> bool {
469 T::is_type_tracked()
470 }
471 }
472}
473
474mod thread {
475 use std::thread;
476
477 trace_acyclic!(<T> thread::JoinHandle<T>);
478 trace_acyclic!(<T> thread::LocalKey<T>);
479 trace_acyclic!(thread::Thread);
480}
481
482mod phantom {
483 use super::*;
484 use std::marker::PhantomData;
485 impl<T: 'static> Trace for PhantomData<T> {
486 fn trace(&self, _tracer: &mut Tracer) {}
487
488 #[inline]
489 fn is_type_tracked() -> bool {
490 false
491 }
492 }
493 unsafe impl<T: 'static> Acyclic for PhantomData<T> {}
494}
495
496#[cfg(test)]
497mod tests {
498 use super::*;
499 use crate::Cc;
500 use std::cell::{Cell, RefCell};
501
502 #[test]
503 fn test_is_type_tracked() {
504 assert!(!u8::is_type_tracked());
505 assert!(!<f32 as Trace>::is_type_tracked());
506 assert!(!String::is_type_tracked());
507 assert!(!Option::<u32>::is_type_tracked());
508 assert!(!Vec::<u8>::is_type_tracked());
509 assert!(!<(bool, f64)>::is_type_tracked());
510 assert!(!Cell::<u32>::is_type_tracked());
511 assert!(!RefCell::<String>::is_type_tracked());
512 assert!(TraceBox::<dyn Trace>::is_type_tracked());
513 assert!(RefCell::<TraceBox::<dyn Trace>>::is_type_tracked());
514 assert!(RefCell::<Vec::<TraceBox::<dyn Trace>>>::is_type_tracked());
515 assert!(Vec::<RefCell::<TraceBox::<dyn Trace>>>::is_type_tracked());
516 assert!(!Cc::<u8>::is_type_tracked());
517 assert!(!Vec::<Cc::<u8>>::is_type_tracked());
518
519 assert!(!<fn(u8) -> u8>::is_type_tracked());
520 assert!(!<fn(&u8) -> u8>::is_type_tracked());
521 }
522
523 #[test]
524 fn test_is_cyclic_type_tracked() {
525 type C2 = RefCell<Option<Cc<Box<S2>>>>;
526 struct S2(C2);
527 impl Trace for S2 {
528 fn trace(&self, t: &mut Tracer) {
529 self.0.trace(t);
530 }
531 fn is_type_tracked() -> bool {
532 true
534 }
535 }
536
537 assert!(S2::is_type_tracked());
538 }
539}
540
541#[derive(Debug, Clone)]
545pub struct TraceBox<T: ?Sized>(pub Box<T>);
546
547impl<T: ?Sized + Trace> Trace for TraceBox<T> {
548 fn trace(&self, tracer: &mut Tracer<'_>) {
549 self.0.trace(tracer);
550 }
551
552 fn is_type_tracked() -> bool {
553 true
554 }
555}
556unsafe impl<T: ?Sized> Acyclic for TraceBox<T> where T: Acyclic {}
557
558impl<T: ?Sized> From<Box<T>> for TraceBox<T> {
559 fn from(inner: Box<T>) -> Self {
560 Self(inner)
561 }
562}
563
564impl<T: ?Sized> Deref for TraceBox<T> {
565 type Target = T;
566
567 fn deref(&self) -> &Self::Target {
568 &self.0
569 }
570}
571impl<T: Trace + ?Sized> DerefMut for TraceBox<T> {
572 fn deref_mut(&mut self) -> &mut Self::Target {
573 &mut self.0
574 }
575}
576
577impl<T: ?Sized> Borrow<T> for TraceBox<T> {
578 fn borrow(&self) -> &T {
579 &self.0
580 }
581}
582
583impl<T: ?Sized> BorrowMut<T> for TraceBox<T> {
584 fn borrow_mut(&mut self) -> &mut T {
585 &mut self.0
586 }
587}
588
589impl<T: ?Sized> AsRef<T> for TraceBox<T> {
590 fn as_ref(&self) -> &T {
591 &self.0
592 }
593}
594
595impl<T: ?Sized> AsMut<T> for TraceBox<T> {
596 fn as_mut(&mut self) -> &mut T {
597 &mut self.0
598 }
599}