Mark and sweep doesn't stop you from holding references across GC.
If you write e.g.
```
let obj = some_object();
let len : &mut usize = &mut obj.len; // deref_mut
trigger_gc();
use(*len);
```
then you held a reference across the GC, and while it's mark/sweeping created an aliases `&mut` to `len`.
Inlining was mention just because it causes function bodies to be splatting together, and so puts together code that is fine in isolation in a way that may allow Rust to observe UB: if `trigger_gc` was inlined for example then Rust has more information and code available at once, and might use the knowledge to apply some optimizations that are invalid because you caused UB.
Actually, looking at your code the much larger issue is that nothing stops you from doing
```
let obj = some_object();
let obj2 = obj.clone();
let len1 = &mut obj.len;
let len2 = &mut obj2.len;
let n = *len1;
*len2 = 0;
println!("{n}"); // what does this print?
```
because your Deref mut are just creating unconstrained borrow from pointer types that you can copy. This is almost definitely going to cause you bugs in the future, since it opens you up to accidentally writing iterator invalidation and other issues (and even worse than C++ does, because C++ doesn't optimize references as heavily as Rust does borrows)
The issue is that it's a simple footgun as soon as you start adding non-trivial native methods (say, string methods, array.map etc). The only way to make sure that they don't exist is removing the DerefMut impl entirely.
It's not just that it's possible to break the code, but that lack of any checks makes it impossible to detect at either compile-time or runtime and have it "appear to work".
One way to solve it to remove the DerefMut implementation and have it work more like Rc - as in, the user is forced to write `Gc<Cell<T>>` or `Gc<RefCell<T>>` if they want mutability. This solves the aliasing borrows issue at the cost of extra runtime checks with RefCell (and still doesn't prevent you from unsoundly calling `sweep()` while holding a Gc)
If you write e.g.
``` let obj = some_object(); let len : &mut usize = &mut obj.len; // deref_mut trigger_gc(); use(*len); ```
then you held a reference across the GC, and while it's mark/sweeping created an aliases `&mut` to `len`.
Inlining was mention just because it causes function bodies to be splatting together, and so puts together code that is fine in isolation in a way that may allow Rust to observe UB: if `trigger_gc` was inlined for example then Rust has more information and code available at once, and might use the knowledge to apply some optimizations that are invalid because you caused UB.
Actually, looking at your code the much larger issue is that nothing stops you from doing
``` let obj = some_object(); let obj2 = obj.clone(); let len1 = &mut obj.len; let len2 = &mut obj2.len; let n = *len1; *len2 = 0; println!("{n}"); // what does this print? ``` because your Deref mut are just creating unconstrained borrow from pointer types that you can copy. This is almost definitely going to cause you bugs in the future, since it opens you up to accidentally writing iterator invalidation and other issues (and even worse than C++ does, because C++ doesn't optimize references as heavily as Rust does borrows)