Skip to content

Instantly share code, notes, and snippets.

@shepmaster
Created May 27, 2017 15:38
Show Gist options
  • Save shepmaster/74523a8ccf7167822570df9e26764b99 to your computer and use it in GitHub Desktop.
Save shepmaster/74523a8ccf7167822570df9e26764b99 to your computer and use it in GitHub Desktop.

First things first, whenever confronted with a programming problem, it's invaluable to create a Minimal, Complete, Verifiable Example (MCVE). Inline code, use the unimplemented macro, remove unrelated functions, etc. Here's one such reduction:

use std::slice;
use std::marker;

struct Entity;

trait ViewTrait<'a> {
    type View;
    fn get_view(&'a mut self, entity: &Entity) -> Self::View;
}

struct World<'a, A: 'a + ViewTrait<'a>> {
    components: A,
    phantom: marker::PhantomData<&'a A>,
}

impl<'a, A> World<'a, A>
    where A: 'a + ViewTrait<'a> 
{
    fn iter(&self) -> slice::Iter<Entity> {
        unimplemented!()
    }
}

struct Scheduler<'a, A>
    where A: 'a + ViewTrait<'a>
{
    world: World<'a, A>,
}

impl<'a, A> Scheduler<'a, A>
    where A: 'a + ViewTrait<'a>
{
    pub fn run(&'a mut self) {
        let components: Vec<A::View> = self.world.iter()
            .map(|e| self.world.components.get_view(e))
            .collect();
    }
}

fn main() {}

Note just how much code has nothing to do with your problem. Doing this allows you to focus on just the related code. Every single step (and this took me about 30 minutes!) helps you refine your mental model about where the problem is and what could be contributing. This isn't something specific to Rust; every programming problem can benefit.

Then we can make some larger jumps and try to reproduce the problem from the other direction, starting from scratch. I ended up at

trait Foo<'a> {
    fn do_the_thing(&'a mut self);
}

fn repro<'a, A>(mut foo: A)
    where A: Foo<'a>
{
    let numbers = [1, 2, 3];
    numbers.iter().map(|_| foo.do_the_thing()).count();
}

fn main() {}

Based on this, we can continue reducing the original problem further by removing arguments and return types to get_view.

One thing that comes to light is that the lifetime 'a is important to reproducing the problem. Removing it everywhere allows the code to compile. Moving it from the trait to the method also allows the code to compile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment