BUG/PERF: MaskedArray.__setitem__ validation
- [x] closes #44172
- [x] closes #44186
- [x] tests added / passed
- [x] Ensure all linting tests pass, see [here](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit) for how to run them
- [ ] whatsnew entry

Fixes a bunch of ways we currently allow invalid setting, but ATM does _not_ fix the non-scalar equivalents.

Perf example from #44172 OP
```
df = pd.DataFrame([[True, False, pd.NA] * 200] * 200, dtype = "object")
df2 = df.astype("boolean")

%timeit res = df2.apply(lambda row: row.count(), axis = 1)
3.9 s ± 192 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)  # <- main
886 ms ± 40.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)  # <- PR
```
what's the bug fix here? > what's the bug fix here?

```
arr = pd.array([True, False])
arr[0] = pd.NaT  # <- fails to raise
```
 > > what's the bug fix here?
> 
> ```
> arr = pd.array([True, False])
> arr[0] = pd.NaT  # <- fails to raise
> ```

kk prob worth a note in a followon @jbrockmendel seems something related to setitem is breaking on master: https://dev.azure.com/pandas-dev/pandas/_build/results?buildId=72425&view=logs&j=e2350215-d973-503e-a41e-d287ff823797&t=751e993b-1954-5330-832a-a54bd1064f7d&l=44 yah just put up a PR that should fix it