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