Taking a step back and thinking about easy solutions, I came up with the idea of using a marker type + lint for this, like:
fn read(&mut self, buf: &mut [u8] + WriteOnly) -> Result<usize>;
The lint would then need to get a typed AST and err on any deref outside of an lvalue. The marker type would not even need to be generic, and could be defined now, even if we haven’t implemented the lint yet.
If that works, it would obviate the need to have a wrapper which would either be specific to one type, e.g. &mut [u8] (which would limit its function to byte buffers), or would need to be generic over the wrapped type (which, barring HKT could entail its own set of problems).
Would that be feasible or do I give Rust’s type system too much credit? Did I get the syntax right? How hard is it to get a typed AST within a lint?
Edit: No, that apparently does not work, because we cannot add trait bounds to concrete types. Too bad. It would have been a cool possibility.