Here we are, yet another one of those boring "first Rust project" question, but I feel like I should start from "somewhere" and that "somewhere" is probably here.
If you would ask me to design you a solution for the classic snake game (with discrete tiles), using GRASP patterns, SOLID patterns, GOF patterns and what not, I would produce you a UML model like this, which I could trivially implement in any OOP langauage such as Java, Python, C++, ecc...
But this apparently trivial design poses some nasty borrowing problem in a Rust implementation.
I'm not asking you to give me a Rust implementation in the answer but to explain me how should i handle the borrowings here, or how should i edit my design if a safe implementation is not possible.
Now, before moving on, I can hear you scream from here that this is probably a XY problem and if you're thinking "Dude all this desgin stuff is simply an overkill! I could implement snake in rust in 300 LOC with way better performance than you will ever achieve" you're probably right, but to designing application like this means also to be able to handle upredictable, growing complexities without a complete rewriting of the implementation.
"Where in the hell would you find upredictable, growing complexities in your personal classic snake game project?" you would ask, and i would answer you nowhere! But bear in mind that the class diagrams proposed in this question isn't something crazy and contains constuct used almost in any OOP project in my experience.
The first problem is that the Snake object will send messages to the Board object during it's lifetime, so it will need a reference to it, but the SnakeGame class holds both the Snake and the Board instances so creating a Snake object in its contructor is non trivial.
I could encapsuate the Board object in a Rc and clone it in the constructor or encapsulate the Snake in an Option and using a second operation init() to actually initializa the Snake object, but both the solution have easily noticeable drawbacks.
The single squares in the Board not having a defined size must me enclosed in a Box or in a Rc, but when the Snake object calls the polymorphic on_collision() method the naked Square, stripped by the Box or Rc won't be able to call back the move_into() or grow_into() Snake's methods wich obviously need the right Box or Rc to operate.
There are way more details and problems but I will stop here hoping to not being too wordy, as stated before I would like your tought and guidance on how to implement this design or how to edit the design in a "Rusty" way. Finding these difficulties makes me wonder if designing complex application in Rust would require a paradigm change on the way i design software.