Skip to content

Questions about subreferences #50

@Shatur

Description

@Shatur

First, thanks for implementing it! I have a few questions about the usage.

I don't own the types for which I need derive LuaUserData, so I came up with this:

#[derive(LuaUserData)]
#[repr(transparent)]
struct ScriptApp(App);

#[lua_methods]
impl ScriptApp {
    pub fn world(&mut self) -> &mut ScriptWorld {
        let world = self.0.world_mut();
        ScriptWorld::from_world_mut(world)
    }
}

#[derive(LuaUserData)]
#[repr(transparent)]
struct ScriptWorld(World);

impl ScriptWorld {
    fn from_world_mut(world: &mut World) -> &mut Self {
        // SAFETY: the type is transparent over `World`.
        unsafe { &mut *(world as *mut World as *mut ScriptWorld) }
    }
}

Here App can return world, but since it doesn't implement UserDataTrait, I just cast it. I think it's a necessary hack, users won't need to do this for their own types. And since the returned reference will live as long as the original one, this should be safe, right?

But I also have this:

#[lua_methods]
impl ScriptWorld {
    fn spawn_empty(&mut self) -> ScriptWorldEntity {
        let entity = self.0.spawn_empty();
        let entity = unsafe {
            std::mem::transmute::<EntityWorldMut<'_>, EntityWorldMut<'static>>(entity)
        };
        ScriptWorldEntity(entity)
    }
}

#[derive(LuaUserData)]
struct ScriptWorldEntity(EntityWorldMut<'static>);

#[lua_methods]
impl ScriptWorldEntity {}

The returned EntityWorldMut has a lifetime over World. Since I can't return static reference, I erase the lifetime. But I assume in this case it's not safe since ScriptWorldEntity won't be considered as a reference, right?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions