Make `#[derive(Copy)]` enough for both `Clone` and `Copy`

Your thread is exactly the same idea! I didn't do a good job at finding duplicate threads.

I didn't understand how your proposed switch works exactly. Do you think the switch is necessary? Or just changing the behavior over an edition would suffice?

The Clone derive already does that, so there is no argument here (there is some order required between the derives, I don't remember which should be above and which below, but if they're on the same line it always works).

Not true, since old editions must still be supported by the compiler.

Interesting, I wasn't aware of that. It seems doesn't work in all cases though, e.g. with a generic parameter I see this:

struct Foo<T> {
    a: T,
    b: T,
    c: T,
}
#[attr = AutomaticallyDerived]
impl <T> ::core::clone::Clone for Foo<T> where T: ::core::clone::Clone {
    #[attr = Inline(Hint)]
    fn clone(&self)
        ->
            Foo<T> {
        Foo {
            a: ::core::clone::Clone::clone(&self.a),
            b: ::core::clone::Clone::clone(&self.b),
            c: ::core::clone::Clone::clone(&self.c) }
    }
}

Might be something related to backward compatibility.

I meant dropping the original #[rustc_ignore_this_impl_in_case_of_conflict] proposal and doing this only over an edition. That is, #[derive(Copy)] in a new edition is equivalent of both Clone and Copy, and adding another Clone impl (either manually or via derive) is a hard error, and not touching the current editions at all.

Your proposal won't be able to support this case anyway, it is impossible without specialization. Unless you constrain Clone to T: Copy, but this significantly changes behavior and not something you can do if you want your proposal to be drop-in.

That does not matter, since the only edition still need to be supported, and the code for it must still be inside the compiler.

You are right.

I didn't get it. What do you mean by "the only edition"? I think without that attribute, the only change needed in the compiler is that the Copy derive macro should resolve to edition2027::Copy builtin macro, which is almost nothing relative to other edition changes in terms of complexity. If we remove the Clone near Copy detection in the current compiler you mentioned, I guess the implementation actually become simpler.

I think they meant to write "the other editions".

In general an edition barrier cannot be used to change the semantics of the Rust standard library, because that library has to be usable by all editions, especially when code from one edition is talking to code from another edition. I assume this is what chrefr was alluding to.

An argument could probably be made that the idea was merely a syntactic change, not a semantic one. However, I'm pretty sure it's generally considered undesirable for the same source code to silently change meanings across an edition, since even with perfect tooling we can't be 100% sure that all code upgraded to a new edition passed through a particular transformation first. It's much better if the code whose meaning is changing will fail to compile in either the old or the new edition, so that it's impossible to forget to do the transformation. And I don't think there's any way to accomplish that when it comes to implicit derives of standard traits

I assumed you want to implement this change before the nearest edition, and only make the hack not required on an edition, by virtue of always generating a Clone impl. To that I responded that it won't help the compiler complexity.

If you meant to wait until an edition and only then apply this change, then you're right - it won't require much complexity in the compiler, though we still need to consider the ecosystem churn.

1 Like