The trait idea is quite neat
, although it would break for callers used to writing .boxed() or .boxed_local() over Box::pin. Hence why I personally find that that "discarded argument" approach with a PhantomData or an empty array can be less surprising.
As was written in the linked post, yeah you could even have a PhantomBound or something to express the intent even clearer.
In general, PhantomData<T> is a bit superior to [T; 0] insofar it doesn't raise the alignment of the data structure. But for a zero-sized parameter passed by value, the alignment doesn't matter, and writing [] is easier than writing PhantomData, hence my going for [], here.
Finally, in your case, in order to improve the ergonomics, you could instead wrap the parameter s, and use, for instance, a &'a &'max mut str[1], or some &'a Str<'max> for some helper type Str<'max> that is Deref<Target = str>. I still think I'd just go for the discarded parameter.
It is sound to transmute
&'a &'a Tto&'a &'_ mut T↩︎