Skip to content
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

Unions require Copy fields, but ignore regions in the check #98102

Open
Mark-Simulacrum opened this issue Jun 14, 2022 · 12 comments
Open

Unions require Copy fields, but ignore regions in the check #98102

Mark-Simulacrum opened this issue Jun 14, 2022 · 12 comments
Labels
T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Mark-Simulacrum
Copy link
Member

Mark-Simulacrum commented Jun 14, 2022

union Bar<'a> {
    v: Foo<'a>,
}

struct Foo<'a> { s: &'a u32 }

impl Copy for Foo<'static> {}
impl Clone for Foo<'static> { fn clone(&self) -> Self { *self } }

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4cc269cb234497a007039d6ddbc41943

It seems to me that the above code should probably be rejected, since in general Foo<'a> doesn't implement Copy in the above code.

The compiler check is checking for "is_copy_modulo_regions" specifically https://github.com/rust-lang/rust/blob/master/compiler/rustc_passes/src/stability.rs#L780, which seems like it probably shouldn't be modulo regions?

@Mark-Simulacrum Mark-Simulacrum added T-lang Relevant to the language team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 14, 2022
@eggyal
Copy link
Contributor

eggyal commented Jun 14, 2022

But you can't actually instantiate a Bar<'a> unless 'a: 'static (playground):

fn main() {
    let s = 123;
    let v = Foo { s: &s };
    Bar { v };
}

results in—

error[E0597]: `s` does not live long enough
  --> src/main.rs:12:22
   |
12 |     let v = Foo { s: &s };
   |                      ^^ borrowed value does not live long enough
13 |     Bar { v };
   |           - copying this value requires that `s` is borrowed for `'static`
14 | }
   | - `s` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.

@Mark-Simulacrum Mark-Simulacrum added A-diagnostics Area: Messages for errors, warnings, and lints and removed T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Jun 14, 2022
@compiler-errors compiler-errors removed the A-diagnostics Area: Messages for errors, warnings, and lints label Jun 15, 2022
@compiler-errors
Copy link
Member

compiler-errors commented Jun 15, 2022

Removing A-diagnostics because I don' t think this is a diagnostics issue necessarily. I can modify the check that we use for checking the union's field are Copy to consider regions, though.

@rustbot claim

@Mark-Simulacrum
Copy link
Member Author

Yeah. I think it's a breaking change potentially to change this now, so it might not be worth making any movement here.

I think in practice there's no risk here, since I believe any Copy impl does forbid all Drop impls, since Drop must be implemented modulo regions always.

@ChayimFriedman2
Copy link
Contributor

But you can't actually instantiate a Bar<'a> unless 'a: 'static

You can instantiate it, and even work with it, but you can't move the maybe-Copy value. This is not related to the union even: for example,

fn main() {
    let mut s = 123;
    let v = Foo { s: &mut s };
    let v = v; // Works if I comment this line
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=e841837a7c635fb568db6814608b66cb

error[E0597]: `s` does not live long enough
  --> src/main.rs:14:22
   |
14 |     let v = Foo { s: &mut s };
   |                      ^^^^^^ borrowed value does not live long enough
15 |     let v = v; // Works if I comment this line
   |             - copying this value requires that `s` is borrowed for `'static`
16 | }
   | - `s` dropped here while still borrowed

@compiler-errors
Copy link
Member

@Mark-Simulacrum: In #55149 (comment), @joshtriplett said:

We'd like to close the remainder of this, and just not allow non-Copy union fields in general, changing that from a feature gate to an error.

I think promoting this to do a copy check considering regions is probably still worth considering here?

@Mark-Simulacrum
Copy link
Member Author

It's probably worth a crater run, at least, but I'm not sure how that comment is relevant. It would be (IMO) the right behavior, but it would also be a breaking change in theory, at least, which makes me reluctant to move ahead with it.

@eggyal
Copy link
Contributor

eggyal commented Jun 20, 2022

You can instantiate it, and even work with it

I can't find a way to instantiate with only safe code.

Doing it via unsafe code (at least the ways I've thought about, like transmute) would violate documented safety conditions.

Is there actually some unsoundness here that I've overlooked? If so this should be I-unsound no?

@ChayimFriedman2
Copy link
Contributor

I can't find a way to instantiate with only safe code.

fn main() {
    let s = 123;
    let union = Bar { v: Foo { s: &s } };
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b8b1891b6c3f22593205919b0f070ede

But I don't think this deserves I-unsound since the moment you'll try to move the inner Foo you'll get a "does not live long enough" error.

@ChayimFriedman2
Copy link
Contributor

ChayimFriedman2 commented Jun 20, 2022

In a second thought, I'm not sure: you can impl Copy for the union and then you can duplicate its instances and effectively also duplicate Foos. So maybe there is a soundness issue? We still need unsafe code to access to the member, though, and it doesn't happen on structs.

@eggyal
Copy link
Contributor

eggyal commented Jun 20, 2022

Apologies, I can't have had enough coffee yet. Of course this isn't a soundness issue: it's only about ensuring that destructors are run, or that one is explicitly acknowledging with ManuallyDrop that they won't be (unless, er, manually dropped). Like you say, copying the union isn't an issue because its fields can't be accessed without unsafe.

@compiler-errors compiler-errors removed their assignment Aug 5, 2022
@Enselic
Copy link
Member

Enselic commented Apr 23, 2024

Triage: There doesn't seem to be anything actionable here? Closing.

@Enselic Enselic closed this as not planned Won't fix, can't repro, duplicate, stale Apr 23, 2024
@compiler-errors
Copy link
Member

Why is this not actionable? Someone should probably implement this check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants