-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Array and Vec's Clone specialization is maybe unsound with conditionally Copy types. #132442
Comments
I believe it was discussed before, and the conclusion was that the specialization is okay and it's invalid to implement |
@theemathas Is this at all specific to the array impl? Can you do the same thing with rust/library/alloc/src/slice.rs Line 156 in a8e1186
|
Yes. This code also doesn't print anything. struct Weird<'a>(&'a i32);
impl Clone for Weird<'_> {
fn clone(&self) -> Self {
println!("clone() called");
Weird(self.0)
}
}
impl Copy for Weird<'static> {}
fn main() {
let local = 1;
let _ = vec![Weird(&local)].clone();
} |
Implementing copy conditionally on lifetimes is nonsensical and unsupported. MIR building will lower all moves of such a value to copy's, which borrowck will then error about when it's not static. |
More discussion of |
Related to #89948. I think that until we actually forbid such Whether rust/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs Lines 58 to 66 in 7fbd4ce
However, given that |
I found a somewhat popular crate (2K stars) that specifically depends on this Clone specialization existing, and depends on a Copy impl that is conditional on type equality. /// Returns if the type `T` is equal to `U`, ignoring lifetimes.
|
Note that it's possible to avoid this specialization by using the |
lol, this issue has been known since 2020 in #71321 rust/library/core/src/marker.rs Lines 408 to 413 in 9fa9ef3
|
Note that there's plenty other uses of |
It's also worth noting that there's nothing in the docs that says |
https://doc.rust-lang.org/std/clone/trait.Clone.html#how-can-i-implement-clone
|
We don't need to accommodate that though, since it's not part of our stable API. I have asked people to not propagate this hack without attaching the appropriate warnings, but it appears that I'm shouting into the void. |
People do that because it solves a problem other methods can't solve. Adding an intended solution to macro_rules! implements_for_static {
($type:ty: $($trait:tt)*) => { /* compiler intrinsic */ };
}; such that |
I have not heard this as an official t-types opinion. If it is, we should start linting against this. |
WG-prioritization assigning priority (Zulip discussion). @rustbot label -I-prioritize +P-medium |
E-needs-investigation: should figure out if a decision was made previously and why, and if this should be linted against going forward. |
Currently, the
Clone
impl for[T; N]
uses specialization. IfT
implementsCopy
, then cloning a[T; N]
will do a memcpy (ignoringT
'sClone
impl). IfT
doesn't implementCopy
, then it will iterate and callT
'sClone
impl.However, specialization doesn't look at lifetimes. Therefore, even if
T
implementsCopy
for only some lifetimes, cloning a[T; N]
will do a memcopy. This is incorrect in the case whereT
actually doesn't implementCopy
. For example:In the above code,
Weird
only implementsCopy
when its lifetime is'static
. Therefore, I think that cloning a[Weird<'a>; 1]
should call theclone()
method. However, running the above code in either stable (1.82.0) or nightly (1.84.0-nightly (2024-10-30 759e07f063fb8e6306ff)
) rust doesn't print anything. I believe that this is incorrect.I am unsure whether or not this can cause UB in purely safe code, (hence the "maybe" in the issue title). But maybe someone else could figure out how to do that?
However, I have written this code, which uses unsafe code to implement a
WeirdCow
type whose public API I believe is sound on its own, but can be used in combination with array's Clone specialization to cause use-after-free. Either thisWeirdCow
type is unsound, or the array's Clone implementation is unsound, and I can't figure out which.@rustbot label +I-unsound
The text was updated successfully, but these errors were encountered: