Pretty much every single suggestion I’ve seen in this area has too little plumbing to be sound wrt lifetime inference and borrow-checking.
However, the “revival” idea is promising in another form, which is that Option<&'a mut T> ought to be copyable under some circumstances, but it can’t be Copy because that’d produce two seemingly-unrelated mutable references.
But if we had a way to change the type of the copy, to, say, Option<&'b mut T> (where 'b is shorter than 'a), then it would be a perfectly valid copy, which means:
// TODO: better names
trait CloneShrink<'a, T> {
// Could this work without `&'a mut self`?
fn clone_shrink(&'a mut self) -> T;
}
impl<'a, T: Clone> CloneShrink<'a, T> for T {
fn clone_shrink(&mut self) -> T {
self.clone()
}
}
// #[lang = "copy_shrink"]
// The compiler would need to enforce that `T: CopyShrink<U>`
// cannot exist unless `T` and `U` only differ by lifetimes.
// e.g. `T = U` and `T = Foo<'a>, U = Foo<'b>` are both valid,
// but `T = Foo<'a>, U = &'b Bar` isn't.
// GATs would make this easier by requiring that you have
// `T = Self::GAT<'a>, U = Self::GAT<'b>`.
trait CopyShrink<'a, T>: CloneShrink<'a, T> {}
impl<'a, T: Copy> CopyShrink<'a, T> for T {}
impl<'a: 'b, 'b, T: ?Sized> CloneShrink<'b, &'b mut T> for &'a mut T {
fn clone_shrink(&'b mut self) -> &'b mut T {
*self
}
}
fn main() {
let mut x = &mut 0;
*x.clone_shrink() += 1;
println!("{}", x)
}
That exact code errors with this funny note:
= note: downstream crates may implement trait `std::clone::Clone` for type `&mut _`
But if you remove the blanket impls, it does work, which means the compiler should be able to integrate CopyShrink in its is-copyable checks, without a lot of design and implementation work.
cc @nikomatsakis @pnkfelix
EDIT: I realize now, after reaching something that works (or at least can be tested for the “Clone” equivalent), that I likely ended up the same point @dhardy started from, with the main difference being associated type vs type parameter (we can do type parameter today, with a small check on every impl).