You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since 0e2d67a, IntoIter now always yields Mut<T> for mutable components. In the latest published release, this was only true for components with tracking enabled, e.g. using the derive macro with #[track(Modification)].
There is one big problem with this new approach because field accesses to mutable components go through DerefMut which is not supported by two-phase borrows with operator traits like AddAssign. See:
Any component that has a struct field with a bitwise assignment operator implementation will have borrow check errors for code that normally wouldn't (without the DerefMut). An example using glam::Vec2 for its AddAssign impl:
use glam::f32::Vec2;use shipyard::{Component,IntoIteras _,ViewMut,World};#[derive(Component,Debug)]structCalc{vec:Vec2,scale:f32,}fnmain(){let world = World::new();
world.run(|mutcalc:ViewMut<Calc>| {formut calc in(&mut calc).iter(){
calc.vec += calc.scale;}});}
This works on the released version (0.6.2, with a warning about an unnecessary mutable variable), but fails on git HEAD:
error[E0502]: cannot borrow `calc` as immutable because it is also borrowed as mutable
--> src\main.rs:15:25
|
15 | calc.vec += calc.scale;
| ------------^^^^------
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here
|
help: try adding a local storing this...
--> src\main.rs:15:25
|
15 | calc.vec += calc.scale;
| ^^^^^^^^^^
help: ...and then using that local here
--> src\main.rs:15:13
|
15 | calc.vec += calc.scale;
| ^^^^^^^^^^^^^^^^^^^^^^
The workaround is trivial, just bind calc.scale to a temporary variable and add-assign with that on the right-hand side. But this is a pretty clear breaking change, and also a gnarly UX.
It would be nice to be able to get &mut Calc out of the iterator instead of Mut<Calc>. Both because it causes this issue, and because I don't need mutation tracking. That sounds like unnecessary overhead for default iteration behavior, doesn't it?
I am not sure what motivated the change, maybe #157 (comment) had something to do with it?
The text was updated successfully, but these errors were encountered:
I think this is the third or forth iteration on the modification tracking design. So far they all come with some big problem but some of them can't even be worked around.
Since 0e2d67a,
IntoIter
now always yieldsMut<T>
for mutable components. In the latest published release, this was only true for components with tracking enabled, e.g. using the derive macro with#[track(Modification)]
.There is one big problem with this new approach because field accesses to mutable components go through
DerefMut
which is not supported by two-phase borrows with operator traits likeAddAssign
. See:vec.swap(0, vec.len() - 1)
, whilevec.push(vec.len())
works. rust-lang/rust#74319Any component that has a struct field with a bitwise assignment operator implementation will have borrow check errors for code that normally wouldn't (without the
DerefMut
). An example usingglam::Vec2
for itsAddAssign
impl:This works on the released version (0.6.2, with a warning about an unnecessary mutable variable), but fails on git
HEAD
:The workaround is trivial, just bind
calc.scale
to a temporary variable and add-assign with that on the right-hand side. But this is a pretty clear breaking change, and also a gnarly UX.It would be nice to be able to get
&mut Calc
out of the iterator instead ofMut<Calc>
. Both because it causes this issue, and because I don't need mutation tracking. That sounds like unnecessary overhead for default iteration behavior, doesn't it?I am not sure what motivated the change, maybe #157 (comment) had something to do with it?
The text was updated successfully, but these errors were encountered: