Say we want to make a simple 2D game. The (imaginary) framework we're using provides the following API: ```rust /// An interactive application drawn on a two-dimensional surface. pub trait Application { /// Draws the UI for the application. fn draw(&self); /// Updates the state of the application in response to the passage of time. fn update(&mut self, step: f32); } /// Runs an [`Application`]. pub fn run_app(mut app: impl Application + 'static); /// An interface to a graphics device used for drawing and managing textures. pub struct Device { ... }; impl Device { /// Creates a new [`Device`]. pub fn new() -> Self; /// Loads a texture by name. pub fn load_texture(&self, name: &'static str) -> u32; /// Unloads a texture. pub fn unload_texture(&self, id: u32); /// Draws a rectangular section of a [`Texture`] to the screen. pub fn draw_texture<'a>( &self, id: u32, uv_min: (u32, u32), uv_max: (u32, u32), pos: (f32, f32), ); } ``` We will need to create an implementation of `Application` which manages the state for the game. This state includes a set of entities where each entity has a position, velocity and sprite used for drawing. A sprite is a rectangular section of a texture (sprites are packed together in the same texture for [performance reasons](https://en.wikipedia.org/wiki/Texture_atlas)). Feeling adventurous, we will model this with liberal use of references: ```rust /// Identifies a texture resource owned by a [`Device`]. pub struct Texture<'a> { device: &'a Device, id: u32 } impl<'a> Texture<'a> { /// Loads a texture by name. pub fn load(device: &'a Device, name: &'static str) -> Self { Self { device: &device, id: device.load_texture(name) } } } impl<'a> Drop for Texture<'a> { fn drop(&mut self) { self.device.unload_texture(self.id) } } /// Identifies a rectangular section of a [`Texture`] used as an individual sprite. #[derive(Clone, Copy)] pub struct Sprite<'a> { texture: &'a Texture<'a>, uv_min: (u32, u32), uv_max: (u32, u32), } /// A game entity, drawn using a single [`Sprite`]. pub struct Entity<'a> { sprite: Sprite<'a>, pos: (f32, f32), vel: (f32, f32), } /// Encapsulates the game state at a particular moment. pub struct Game<'a> { device: &'a Device, background: &'a Texture<'a>, entities: Vec>, } impl<'a> Application for Game<'a> { ... } ``` Now, let's just create an instance of `Game` and pass it to `run_app`: ```rust fn main() { let device = Device::new(); let background = Texture::load(&device, "background.png"); let atlas = Texture::load(&device, "atlas.png"); let player_sprite = Sprite { texture: &atlas, uv_min: (0, 0), uv_max: (64, 64) }; let goombler_sprite = Sprite { texture: &atlas, uv_min: (64, 0), uv_max: (128, 64) }; run_app(Game { device: &device, background: &background, entities: vec![ Entity { sprite: player_sprite, pos: (0.0, 0.0), vel: (10.0, 0.0) }, Entity { sprite: goombler_sprite, pos: (200.0, 0.0), vel: (-10.0, 0.0) }, Entity { sprite: goombler_sprite, pos: (400.0, 0.0), vel: (-10.0, 0.0) } ] }); } ``` Just compile and we should be good to go! ... ... ... Uh oh ``` error[E0597]: `device` does not live long enough error[E0597]: `device` does not live long enough error[E0597]: `atlas` does not live long enough error[E0597]: `atlas` does not live long enough error[E0597]: `device` does not live long enough error[E0597]: `background` does not live long enough ``` Looks like we missed the `'static` bound on `run_app`. This is actually a pretty big problem. On some platforms (e.g. web), the event loop doesn't start until after the main entry point returns. That means we can't have any stack-allocated data persisting between events. This calls our entire reference-based design into question. In times not long ago, we would be reaching for [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) or [`Box::leak`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak). But now we have a new tool at our disposal: Fortify! Instead of passing `run_app` a `Game<'a>`, we can pass it a `Fortify>`. Let's assume the application framework was kind enough to provide the following implementation: ```rust impl Application for Fortify where for<'a> T: Lower<'a>, for<'a> >::Target: Application, { fn draw(&self) { self.borrow().draw() } fn update(&mut self, step: f32) { self.with_mut(|app| app.update(step)) } } ``` *(It's okay if it doesn't. It just saves us the trouble of creating a wrapper type and doing it ourselves)* Now, lets bundle up all of our game's resources using the `fortify!` macro and try again: ```rust fn main() { run_app(fortify! { let device = Device::new(); let background = Texture::load(&device, "background.png"); let atlas = Texture::load(&device, "atlas.png"); let player_sprite = Sprite { texture: &atlas, uv_min: (0, 0), uv_max: (64, 64) }; let goombler_sprite = Sprite { texture: &atlas, uv_min: (64, 0), uv_max: (128, 64) }; yield Game { device: &device, background: &background, entities: vec![ Entity { sprite: player_sprite, pos: (0.0, 0.0), vel: (10.0, 0.0) }, Entity { sprite: goombler_sprite, pos: (200.0, 0.0), vel: (-10.0, 0.0) }, Entity { sprite: goombler_sprite, pos: (400.0, 0.0), vel: (-10.0, 0.0) } ] }; }); } ``` Success! With a minor reorganization of the setup code, we were able to promote stack-allocated variables into long-lived resources. Check out the full code for this example [here](https://github.com/dzamkov/fortify/blob/master/tests/game.rs).