I’ve been working on a platformer game in rust. Game objects are stored in a Vec, and each is updated independently. However, a given object would like to interact with other objects. In C I would do something like fn update(&mut self, others: &mut [Self]). However, this would result in the parameters being aliased, which is not allowed.

What I’m looking for is some type that acts like a &mut [T], but remembers which element it is not allowed to access. I could use two &mut [T] values, built with split_at_mut, but this is unwieldy. I could make a struct that contains both. Is there a crate that does this? Ideally it would use unsafe internally so the compiler knows there is exactly one element in between. (that is to say, I would prefer something using only 24 bytes)

Chain does not do what I want because it can only be used as an iterator, not for indexing. To be clear, I would like to be able to index the result exactly like a &mut [T], except that it will find the element under consideration to be out of range.

  • BB_C@programming.dev
    link
    fedilink
    arrow-up
    2
    ·
    19 days ago

    Using cells in your solution is smelly, when you can simply use two transparent wrappers with Ref or RefMut access, so you have actual compile-time checking instead of janky checking at runtime (which is also not zero-cost).

    The allow/deny variants could themselves hold & or &mut references too if we are going with that route. But it all depends on the precise problem OP is having and what is the best workable solution for it looks like.

    • ExperimentalGuy@programming.dev
      link
      fedilink
      arrow-up
      2
      ·
      19 days ago

      How is it a code smell? I’m pretty sure interior mutability is a well established design pattern. I’m not really familiar with the pattern you’re describing using Ref/RefMut wrapping, could you show me what you mean?

      Yeah I didn’t want to pour a bunch of time into wrangling borrow checker stuff for a small code snippet.

      • BB_C@programming.dev
        link
        fedilink
        arrow-up
        2
        ·
        19 days ago

        Actually, I didn’t notice your use of clone() which is even worse.

        Here is what I had in mind. One can put the T: Default bound on the wrappers themselves to simplify, or add potentially expensive transformations for non-Default types.

        • ExperimentalGuy@programming.dev
          link
          fedilink
          arrow-up
          1
          ·
          18 days ago

          Yeah what I wrote was just something to get the idea out, about having a list of Allowables.

          I just fully read your code, and I like how you changed the Allowable api to have a deny and allow function instead of it being at the AllowList level. Honestly, I did not know mem::take was a function. I like how you got around cloning too.

          Also, just so you know, you come off pretty rude. Just want to make sure you know that if you’re not aware.