API / CoW: return read-only numpy arrays in .values/to_numpy()
Context: with the Copy-on-Write implementation (see overview follow up issue https://github.com/pandas-dev/pandas/issues/48998), we can avoid that mutating one pandas object doesn't update another pandas object. But users can still easily get a viewing numpy array, and mutate that one. And at that point, we don't have any control over how this mutation propagates (it might update more objects than just the one from which the user obtained it, for example if other Series/DataFrames were sharing data with this object with CoW). 

This is a draft PR just starting to explore this (see how much fails in our own test suite, to get an idea of the impact)
This needs some more tests, and currently also doesn't yet handle EAs (eg np.asarray(Series[Int64])) Couple smaller comments. I think this is something we should document explicitly. But can do as follow up I guesss I added an explicit test for the failing `np.fix` case (currently this was called randomly in an unrelated indexing test). 

The problem with `np.fix` is that this is basically implemented under the hood as:

```
res = np.asanyarray(np.ceil(x))
res = np.floor(x, out=res, where=np.greater_equal(x, 0))
```

And so the `np.asanyarray` result now gives a read-only array, but this is passed in a second step as the `out` parameter, trying to write values into it.

In this case if the `np.asanyarray` and `np.ceil` calls would be inversed, it would work (first converting to read-only numpy array, and then np.ceil operation would effectively return a new writeable array) thx @jorisvandenbossche  cc @seberg @phofl my comment above at https://github.com/pandas-dev/pandas/pull/51082#issuecomment-1455882487 is the case that I was remembering where our change to read-only broke a legit case of calling a numpy function on a Series object: normally, the np.ceil call should make it writeable, but because this is wrapped again in a Series (since `np.ceil` is a ufunc), this new writeable array becomes again read-only when converted back to numpy, and then passing this to the `out` param in `np.floor` gives an error. 
This causes an actual regression from the pandas' user point of view, while it could still work. I don't know if for numpy there is a specific reason to do `np.asanyarray(np.ceil(x))` instead of `np.ceil(np.asanyarray(x))`? Although I suppose because you want to allow the object to use its overridden version through `__array_ufunc__`, and converting it to an array first would defeat that. The `asanyarray` is really there for an obscure purpose probably (numpy converting 0-D arrays to scalars mostly).  But yeah, it is also needed since only arrays are considered valid `out=` arguments (although I have to double check `__array_prepare__` might allow it, but OTOH, I don't think it ever fully worked.

In either case, since we call it along the way, you are right that it would be fine to _add_ an `asanyarray` call at the beginning.