Skip to main content

BankSafe

Trait BankSafe 

Source
pub unsafe auto trait BankSafe { }
Available on crate feature bank only.
Expand description

A value safe to carry across a bank switch: it embeds no pointer to banked code that the switch would unmap.

This is the bank-switching analog of the standard library’s std::panic::UnwindSafe, and like it an auto trait: a type is BankSafe unless it contains something that is not, so the property propagates through structs, tuples, and enums. A generic type parameter that reaches a switch therefore needs an explicit BankSafe bound, the same way crossing a thread boundary needs Send.

§What is not BankSafe

A bare fn pointer and a dyn trait object, because calling either performs no bank switch: if it targets banked code, the caller runs it with that bank unmapped. Far and DynFar are the sanctioned carriers and are exempt, because calling one switches banks first (and costs nothing when the target is bank 0).

Anchor is excluded for a different reason: it witnesses that the current code is in bank 0, which reaching a banked callee would falsify.

§Where it is enforced

Every path that crosses a switch requires it on the values that cross: Warp and FarCall on both their arguments and their output, scope and FarWith::there on what the closure returns.

§Examples

Handing a banked function pointer back to the caller is rejected:

#[bank]
pub fn pick() -> fn() {
    fn helper() { /* lives in this bank */ }
    helper // ERROR: `fn()` is not `BankSafe`
}

So is passing one into another bank, where it would no longer be mapped:

#[bank]
pub fn register(tick: fn()) { // ERROR: `fn()` is not `BankSafe`
    tick()
}

Carry the function as a Far instead; calling it maps its bank first:

#[bank]
fn pick() -> Far<fn(), Sound> {
    far!(sound::helper)
}

A generic banked item needs the bound on any parameter that crosses:

#[bank]
impl<A: Copy + BankSafe> Summary for Pair<A> {
    fn summarize(&self) -> u8 { /* `&Pair<A>` crosses as the receiver */ }
}

§Globals are not covered

The bound only reaches values that pass through an API. A banked function may still park a pointer to its own code in a global and leave it there after the switch, with no unsafe anywhere:

static CB: Mutex<Cell<Option<fn()>>> = Mutex::new(Cell::new(None));

#[bank]
pub fn install(cs: CriticalSection) {
    fn helper() { /* lives in this bank */ }
    CB.borrow(cs).set(Some(helper)); // accepted
}

// elsewhere, once this bank is no longer mapped
critical_section::with(|cs| CB.borrow(cs).get().unwrap()()); // undefined behaviour

Calling such a pointer runs whatever bytes the currently mapped bank holds at that address. Unlike UnwindSafe, whose violations only expose inconsistent state, a violation here can execute arbitrary code.

A crate that targets the Game Boy and hands out a place to keep global state should bound what goes in it on this trait. General-purpose wrappers cannot, for example critical_section::Mutex, so a banked code pointer still reaches a global through any of them.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

§

impl<F, G, Args> BankSafe for BankedWarp<F, G, Args>
where F: BankSafe, Args: BankSafe, G: BankSafe,

§

impl<M, Args> BankSafe for FixedWarp<M, Args>
where Args: BankSafe, M: BankSafe,

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K, L> !BankSafe for extern "C" fn(A, B, C, D, E, F, G, H, I, J, K, L) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K, L> !BankSafe for fn(A, B, C, D, E, F, G, H, I, J, K, L) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K, L> !BankSafe for unsafe extern "C" fn(A, B, C, D, E, F, G, H, I, J, K, L) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K, L> !BankSafe for unsafe fn(A, B, C, D, E, F, G, H, I, J, K, L) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K> !BankSafe for extern "C" fn(A, B, C, D, E, F, G, H, I, J, K) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K> !BankSafe for fn(A, B, C, D, E, F, G, H, I, J, K) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K> !BankSafe for unsafe extern "C" fn(A, B, C, D, E, F, G, H, I, J, K) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J, K> !BankSafe for unsafe fn(A, B, C, D, E, F, G, H, I, J, K) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J> !BankSafe for extern "C" fn(A, B, C, D, E, F, G, H, I, J) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J> !BankSafe for fn(A, B, C, D, E, F, G, H, I, J) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J> !BankSafe for unsafe extern "C" fn(A, B, C, D, E, F, G, H, I, J) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I, J> !BankSafe for unsafe fn(A, B, C, D, E, F, G, H, I, J) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I> !BankSafe for extern "C" fn(A, B, C, D, E, F, G, H, I) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I> !BankSafe for fn(A, B, C, D, E, F, G, H, I) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I> !BankSafe for unsafe extern "C" fn(A, B, C, D, E, F, G, H, I) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H, I> !BankSafe for unsafe fn(A, B, C, D, E, F, G, H, I) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H> !BankSafe for extern "C" fn(A, B, C, D, E, F, G, H) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H> !BankSafe for fn(A, B, C, D, E, F, G, H) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H> !BankSafe for unsafe extern "C" fn(A, B, C, D, E, F, G, H) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G, H> !BankSafe for unsafe fn(A, B, C, D, E, F, G, H) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G> !BankSafe for extern "C" fn(A, B, C, D, E, F, G) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G> !BankSafe for fn(A, B, C, D, E, F, G) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G> !BankSafe for unsafe extern "C" fn(A, B, C, D, E, F, G) -> Ret

Source§

impl<Ret, A, B, C, D, E, F, G> !BankSafe for unsafe fn(A, B, C, D, E, F, G) -> Ret

Source§

impl<Ret, A, B, C, D, E, F> !BankSafe for extern "C" fn(A, B, C, D, E, F) -> Ret

Source§

impl<Ret, A, B, C, D, E, F> !BankSafe for fn(A, B, C, D, E, F) -> Ret

Source§

impl<Ret, A, B, C, D, E, F> !BankSafe for unsafe extern "C" fn(A, B, C, D, E, F) -> Ret

Source§

impl<Ret, A, B, C, D, E, F> !BankSafe for unsafe fn(A, B, C, D, E, F) -> Ret

Source§

impl<Ret, A, B, C, D, E> !BankSafe for extern "C" fn(A, B, C, D, E) -> Ret

Source§

impl<Ret, A, B, C, D, E> !BankSafe for fn(A, B, C, D, E) -> Ret

Source§

impl<Ret, A, B, C, D, E> !BankSafe for unsafe extern "C" fn(A, B, C, D, E) -> Ret

Source§

impl<Ret, A, B, C, D, E> !BankSafe for unsafe fn(A, B, C, D, E) -> Ret

Source§

impl<Ret, A, B, C, D> !BankSafe for extern "C" fn(A, B, C, D) -> Ret

Source§

impl<Ret, A, B, C, D> !BankSafe for fn(A, B, C, D) -> Ret

Source§

impl<Ret, A, B, C, D> !BankSafe for unsafe extern "C" fn(A, B, C, D) -> Ret

Source§

impl<Ret, A, B, C, D> !BankSafe for unsafe fn(A, B, C, D) -> Ret

Source§

impl<Ret, A, B, C> !BankSafe for extern "C" fn(A, B, C) -> Ret

Source§

impl<Ret, A, B, C> !BankSafe for fn(A, B, C) -> Ret

Source§

impl<Ret, A, B, C> !BankSafe for unsafe extern "C" fn(A, B, C) -> Ret

Source§

impl<Ret, A, B, C> !BankSafe for unsafe fn(A, B, C) -> Ret

Source§

impl<Ret, A, B> !BankSafe for extern "C" fn(A, B) -> Ret

Source§

impl<Ret, A, B> !BankSafe for fn(A, B) -> Ret

Source§

impl<Ret, A, B> !BankSafe for unsafe extern "C" fn(A, B) -> Ret

Source§

impl<Ret, A, B> !BankSafe for unsafe fn(A, B) -> Ret

Source§

impl<Ret, A> !BankSafe for extern "C" fn(A) -> Ret

Source§

impl<Ret, A> !BankSafe for fn(A) -> Ret

Source§

impl<Ret, A> !BankSafe for unsafe extern "C" fn(A) -> Ret

Source§

impl<Ret, A> !BankSafe for unsafe fn(A) -> Ret

Source§

impl<Ret> !BankSafe for extern "C" fn() -> Ret

Source§

impl<Ret> !BankSafe for fn() -> Ret

Source§

impl<Ret> !BankSafe for unsafe extern "C" fn() -> Ret

Source§

impl<Ret> !BankSafe for unsafe fn() -> Ret

Implementors§

Source§

impl !BankSafe for Anchor

Source§

impl BankSafe for OamDma

Source§

impl<T, G> BankSafe for Far<T, G>
where G: Group, T: ?Sized,

Source§

impl<T> BankSafe for DynFar<T>
where T: ?Sized,

Auto implementors§

§

impl BankSafe for Addressing

§

impl BankSafe for AudioCtrl

§

impl BankSafe for BankNumber

§

impl BankSafe for BgAttr

§

impl BankSafe for Buttons

§

impl BankSafe for Channel

§

impl BankSafe for Color

§

impl BankSafe for DPadX

§

impl BankSafe for DPadY

§

impl BankSafe for Duty

§

impl BankSafe for Envelope

§

impl BankSafe for GroupZero

§

impl BankSafe for HdmaCtrl

§

impl BankSafe for Hz32

§

impl BankSafe for Hz64

§

impl BankSafe for Hz128

§

impl BankSafe for Hz256

§

impl BankSafe for Hz512

§

impl BankSafe for Hz1024

§

impl BankSafe for Hz2048

§

impl BankSafe for Hz4096

§

impl BankSafe for Hz8192

§

impl BankSafe for Hz16384

§

impl BankSafe for Infrared

§

impl BankSafe for Interrupts

§

impl BankSafe for Joypad

§

impl BankSafe for Latch

§

impl BankSafe for Lcdc

§

impl BankSafe for Map

§

impl BankSafe for MasterVolume

§

impl BankSafe for Noise

§

impl BankSafe for NoiseCtrl

§

impl BankSafe for NoiseFreq

§

impl BankSafe for Note

§

impl BankSafe for OamAttr

§

impl BankSafe for OamEntry

§

impl BankSafe for OamShadow

§

impl BankSafe for ObjSlot

§

impl BankSafe for Pad

§

impl BankSafe for Palette

§

impl BankSafe for PaletteIndex

§

impl BankSafe for Panning

§

impl BankSafe for PcmAmplitudes

§

impl BankSafe for PeriodCtrl

§

impl BankSafe for Port

§

impl BankSafe for PpuMode

§

impl BankSafe for Pulse

§

impl BankSafe for PulseLengthDuty

§

impl BankSafe for Rate

§

impl BankSafe for SerialCtrl

§

impl BankSafe for Shade

§

impl BankSafe for Size

§

impl BankSafe for SpeedSwitch

§

impl BankSafe for Stat

§

impl BankSafe for Stream

§

impl BankSafe for Sweep

§

impl BankSafe for Tilt

§

impl BankSafe for Time

§

impl BankSafe for TimerClock

§

impl BankSafe for TimerCtrl

§

impl BankSafe for Transfer

§

impl BankSafe for Vblank

§

impl BankSafe for VramBank

§

impl BankSafe for Wave

§

impl BankSafe for WaveDac

§

impl BankSafe for WaveLevel

§

impl BankSafe for WaveOutput

§

impl<'a, R> BankSafe for Instant<'a, R>
where R: BankSafe,

§

impl<'a> BankSafe for Access<'a>

§

impl<'a> BankSafe for AttrAccess<'a>

§

impl<'a> BankSafe for AttrGrid<'a>

§

impl<'a> BankSafe for TileGrid<'a>

§

impl<'cs> BankSafe for CriticalSection<'cs>

§

impl<G> BankSafe for Bank<G>
where G: BankSafe,

§

impl<R> BankSafe for Duration<R>
where R: BankSafe,

§

impl<R> BankSafe for Timer<R>
where R: BankSafe,

§

impl<T, const BANK: u8> BankSafe for Sram<T, BANK>
where T: BankSafe,

§

impl<T> BankSafe for HramAtomicCell<T>

§

impl<T> BankSafe for HramCell<T>

§

impl<T> BankSafe for Source<T>
where T: BankSafe,

§

impl<const N: usize> BankSafe for HramArea<N>