Scan

Trait Scan 

Source
pub unsafe trait Scan: GcSafe {
    // Required method
    fn scan(&self, scanner: &mut Scanner<'_>);
}
Expand description

A trait capturing the ability of data to be scanned for references to data in a Gc.

This is unsafe, since a bad scan implementation can cause memory unsafety in two ways:

  1. If scan scans data that this object does not own
  2. If scan does anything other than scan data with a non-'static lifetime
  3. If scan is non-deterministic about what owned data it scans

The importance of (1) is so that the collector does not collect data that is in use. The importance of (2) is so that data can still be scanned even after its lifetime has technically expired.

Regarding (1): Note that it’s okay to miss data that you own. Missing connected data can only cause memory leaks–not memory unsafety. Regarding (2): In particular, scan should not call anything but Scan on R and RMut. Even implicitly using the deref implementations on these structs is incorrect.

Importantly, any empty scan implementation is safe (assuming the GcSafe impl is correct)

NB: It’s important that scan only scans data that is truly owned. Rc/Arc cannot have sensible scan implementations, since each individual smart pointer doesn’t own the underlying data.

§Examples

In practice you probably want to use the derive macro:

use shredder::Scan;

#[derive(Scan)]
struct Example {
    v: u32
}

This also comes with a #[shredder(skip_scan)] attribute, for when some data implements GcSafe but not Scan

use std::sync::Arc;
use shredder::Scan;

#[derive(Scan)]
struct Example {
    #[shredder(skip_scan)]
    v: Arc<u32>
}

This can work for any Send+ 'static data using GcSafeWrapper

use std::sync::Arc;

use shredder::marker::GcSafeWrapper;
use shredder::Scan;

struct SendDataButNotScan {
    i: u32
}

#[derive(Scan)]
#[shredder(cant_drop)] // <- To understand why we need this, read the docs of the derive itself
struct Example {
    #[shredder(skip_scan)]
    v: GcSafeWrapper<SendDataButNotScan>
}

In emergencies, you can break out #[shredder(unsafe_skip_gc_safe)], but this is potentially unsafe (the field you’re skipping MUST uphold invariants as-if it was GcSafe)

use std::sync::Arc;
use shredder::Scan;

struct NotEvenSendData {
    data: *mut u32
}

#[derive(Scan)]
#[shredder(cant_drop)] // <- To understand why we need this, read the docs of the derive itself
struct Example {
    #[shredder(unsafe_skip_gc_safe)]
    v: NotEvenSendData
}

IMPORTANT NOTE: You may have problems with the derive complaining your data is not-GcDrop. To find a resolution, read the documentation of the derive itself.

Required Methods§

Source

fn scan(&self, scanner: &mut Scanner<'_>)

scan should use the scanner to scan all of its directly owned data

Implementations on Foreign Types§

Source§

impl Scan for bool

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for f32

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for f64

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for i8

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for i16

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for i32

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for i64

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for i128

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for isize

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for u8

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for u16

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for u32

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for u64

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for u128

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for usize

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for String

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for Duration

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for RandomState

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl Scan for Instant

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl<A: Scan, B: Scan> Scan for (A, B)

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<K: Scan, V: Scan> Scan for BTreeMap<K, V>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<K: Scan, V: Scan, S: BuildHasher + GcSafe> Scan for HashMap<K, V, S>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T> Scan for &'static T

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl<T: Copy + GcSafe + ?Sized> Scan for Cell<T>

Source§

fn scan(&self, _: &mut Scanner<'_>)

Source§

impl<T: Scan + ?Sized> Scan for RefCell<T>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T: Scan + ?Sized> Scan for Mutex<T>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T: Scan + ?Sized> Scan for RwLock<T>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T: Scan> Scan for Option<T>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T: Scan> Scan for BTreeSet<T>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T: Scan> Scan for Vec<T>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T: Scan, E: Scan> Scan for Result<T, E>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Source§

impl<T: Scan, S: BuildHasher + GcSafe> Scan for HashSet<T, S>

Source§

fn scan(&self, scanner: &mut Scanner<'_>)

Implementors§

Source§

impl<'a, T: ?Sized> Scan for R<'a, T>

Source§

impl<'a, T: ?Sized> Scan for RMut<'a, T>

Source§

impl<T: Scan + GcDeref + ?Sized> Scan for DerefGc<T>

Source§

impl<T: Scan + ?Sized> Scan for Gc<T>

Source§

impl<T: Scan> Scan for AtomicGc<T>