Repository: yt-project/unyt

Issue:
Unexpected behaviour when assigning array elements
* unyt version: 2.9.4 (but was always present)
* Python version: 3.10.6 (though not relevant)
* Operating System: irrelevant

### Description

No unit check is performed when assigning elements of an array. This is fairly counter-intuitive behaviour
and can likely lead to user errors downstream.

Here is an example (courtesy in part of @JBorrow):

```python
In [1]: import unyt

In [2]: unyt.__version__
Out[2]: 'v2.9.4'

In [3]: x = unyt.unyt_array([0, 2, 3], "cm")

In [4]: y = unyt.unyt_array([5, 6, 7], "kg")

In [5]: x[1] = 4

In [6]: x[2] = y[0]

In [7]: x
Out[7]: unyt_array([0, 4, 5], 'cm')
```

Lines 5 and 6 show two different problematic cases. Line 5 assigns a dimensionless quantity to a dimensionful array.  That may be OK but is ambiguous. Line 6 is especially problematic as we are now assigning completely invalid units to each other and the code is just happy to go along. 


Discussion:

Patch:
diff --git a/unyt/array.py b/unyt/array.py
index 014f2d2..805afa8 100644
--- a/unyt/array.py
+++ b/unyt/array.py
@@ -1725,6 +1725,11 @@ class unyt_array(np.ndarray):
             ret.units = self.units
         return ret
 
+    def __setitem__(self, item, value):
+        if hasattr(value, "units") and value.units != self.units:
+            value = value.to(self.units)
+        super().__setitem__(item, value)
+
     def __pow__(self, p, mod=None, /):
         """
         Power function


Test patch:
diff --git a/unyt/tests/test_unyt_array.py b/unyt/tests/test_unyt_array.py
index 0d72fbf..66faa7e 100644
--- a/unyt/tests/test_unyt_array.py
+++ b/unyt/tests/test_unyt_array.py
@@ -2752,3 +2752,18 @@ def test_int8_comparison():
     # see regression https://github.com/yt-project/unyt/issues/369
     a = unyt_array(np.zeros(5, dtype=np.int8))
     assert all(e == 0 for e in a)
+
+
+def test_setitem():
+    # see https://github.com/yt-project/unyt/issues/373
+    a = [1, 2, 3] * cm
+    a[1] = 2 * m
+    assert a[1].value == 200
+    assert a[1].units == cm
+
+    with pytest.raises(UnitConversionError):
+        a[1] = 2 * g
+
+    a[1] = 2
+    assert a[1].value == 2
+    assert a[1].units == cm