#Return `&mut dyn Reflect` from a function

26 messages · Page 1 of 1 (latest)

sturdy anvil
#

I have a function that takes in a Mut<'_, dyn Reflect> and a string. It first calls .reflect_mut() on that. if the ReflectMut is a struct it will return a &mut dyn Reflect to the ReflectMut's field with the name of the string you pass in to the function.

The problem is this error:

error[E0515]: cannot return value referencing local variable `var`
    |
473 |                 let reflect_mut = var.reflect_mut();
    |                                   --- `var` is borrowed here
...
487 |                             Ok(field)
    |                             ^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function

Context: var is a Mut<'_, dyn Reflect>

hollow gull
#

The &mut dyn Reflect will be necessarily bound to the lifetime of the Mut<'_, dyn Reflect>. Maybe try rs fn foo<'a>(var: &'a Mut<'_, dyn Reflect>) -> &'a mut dyn Reflect {

sturdy anvil
# hollow gull The `&mut dyn Reflect` will be necessarily bound to the lifetime of the `Mut<'_,...

That works actually. But not in my actual use case. var isnt actually an argument (i just said that for simplicity, but now i have to specify). var is actually defined as:

let Some(mut var) = mut_dyn_reflect(world, registration) else {
  todo!()
};

mut_dyn_reflect is a horribly named function that takes in a &mut World and a &TypeRegistration and converts that to a Mut<'a, dyn Reflect>. The full function is this:

fn mut_dyn_reflect<'a>(
    world: &'a mut World,
    registration: &'a TypeRegistration,
) -> Option<Mut<'a, dyn Reflect>> {
    let Some(component_id) = world.components().get_resource_id(registration.type_id()) else {
        error!(
            "Couldn't get the component id of the {} resource.",
            registration.type_info().type_path()
        );
        return None;
    };
    let resource = world.get_resource_mut_by_id(component_id).unwrap();
    let reflect_from_ptr = registration.data::<ReflectFromPtr>().unwrap();
    // SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`
    let val: Mut<dyn Reflect> =
        resource.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_mut(ptr) });
    Some(val)
}
#

sorry for not specifying earlier, it was easier to explain it as a function argument

hollow gull
#

What are you trying to do with the &mut dyn Reflect specifically?

sturdy anvil
#

wait no thats the wrong function hold on 🤦

#

fixed

hollow gull
#
let Some(mut var) = mut_dyn_reflect(world, registration) else {
    // we can get our `&mut dyn Reflect` here, but if we want it to live longer than this scope, we will have to give up the `Mut<'_, dyn Reflect>` instead
};```
sturdy anvil
hollow gull
#

Ohh

#

You're totally right

#

Well, general rule applies - Currently some scope owns the Mut, and cannot give up a reference to that without also giving the Mut too

sturdy anvil
#

so i how do i also give the Mut

hollow gull
#

well, that's var isn't it?

#

I think you would need to do something like Ok((var, field))

sturdy anvil
#

ah

#

it doesnt work

hollow gull
#

Oh this is probably getting into that cursed territory of self-referential structs

sturdy anvil
#

thonk the what

hollow gull
#

Well, we want to own both a struct and a reference to that struct, and then move them both together - As I understand it, this is rather cursed unless it's Pin

sturdy anvil
#

Pin?

hollow gull
sturdy anvil
hollow gull
#

No, I'm saying this is fundamentally why this is cursed and probably won't work the way I'm thinking

sturdy anvil
#

is there a way to do this that isnt cursed?

hollow gull
#

I'm not really sure a good solution, I think giving the Mut to whoever wants the &mut dyn Reflect and letting them grab/drop the field temporarily as needed