-
Couldn't load subscription status.
- Fork 13.9k
Description
I tried this code:
#[derive(Clone)]
struct Foo<'lt>(&'lt ());
impl Copy for Foo<'static> {}
#[derive(Clone)]
struct Bar<'lt>(Foo<'lt>);
impl<'any> Copy for Bar<'any> {}
fn check(b: Bar<'_>) -> (Bar<'_>, Bar<'_>) {
(b, b)
}- (Note about
#[derive(Clone)]: while this simple snippet features aCloneimpl for all lifetimes, it is possible to restrict the impl ofClone for Footo'staticas well, and yet offer aBar<'any>which isCloneable (thanks to it beingCopyable). See below for a more detailed example about that).
I expected to see this happen:
-
Either the
impl Copy for Bar<'_> {}should have failed, or, at the very least, the borrow checker ought to have complained about the actual copy ofb(from looking at the old related issue, a "late" / on-use borrow-checker issue was deemed good enough since such a check does prevent unsoundness).Alas, we can see here that that check can be dodged by using a wrapper type.
Instead, this happened:
- the code compiled fine.
Meta
stable, beta and nightly are affected by this, and I suspect all versions of Rust do.
Impact
While contrived, this ought to be a I-unsound issue, since a library could feature a lifetime-generic type Foo<'lt> with an exploited safety invariant of Foo<'not_static> not being cloneable. Demo
- That being said, I'd qualify it as low priority, since the example is indeed very contrived.
Bonus / tangential issue 🎁
A type which is only Copy when 'static becomes, in practice / in non-generic context, unmoveable when non-'static:
#[derive(Clone)]
struct Foo<'lt>(&'lt ());
impl Copy for Foo<'static> {}
fn check(f: Foo<'_>) {
assert!(Some(f).is_some()); // Error, lifetime `'static` required
}-
Indeed, the
move_or_copyheuristic decides to go for copy since the type is indeedcopy_modulo_regions, but then the borrow checker (correctly) forbids theCopyoperation since the lifetime isn't (can't be proven to be)'static
Metadata
Metadata
Assignees
Labels
Type
Projects
Status