Description
#![allow(unused)]
#[derive(Clone, Copy, Default)]
struct S {
a: u8,
b: u8,
}
#[derive(Clone, Copy, Default)]
struct Z {
c: u8,
d: u8,
}
union U {
s: S,
z: Z,
}
fn main() { unsafe {
let mut u = U { s: Default::default() };
let mref = &mut u.s.a;
let err = &u.z.c; // This line compiles, but it certainly shouldn't ...
drop(mref); // ... (at least if `mref` is used after `err`)
}}
"Cousins" of borrowed union sub-fields (and their further children) are not marked as borrowed.
The same bug should happen with move checking as well, but I haven't made an example yet.
Activity
nikomatsakis commentedon Jan 18, 2018
This is still true in NLL, though I sort of thought we had tried to fix this.
nikomatsakis commentedon Jan 18, 2018
I'm tagging this as WG-compiler-nll; I think it's something we should fix there.
joshtriplett commentedon Jan 18, 2018
For the sake of potential testsuite additions: this also should not compile with a simultaneous borrow of
u.s.a
andu.z.d
.davidtwco commentedon Jan 22, 2018
I'll take a look at this one.
nikomatsakis commentedon Jan 22, 2018
I'm not really sure what the bug is here, but I can explain what I think should be happening. This function:
rust/src/librustc_mir/borrow_check/mod.rs
Line 1630 in fdc18b3
is responsible for determining when two
Place
values overlap. I expect us to say that two fields from a union are always considered to potentially overlap. In this case,u.s
andu.z
would be considered to overlap. Specifically, comparing those two fields would returnArbitrary
:rust/src/librustc_mir/borrow_check/mod.rs
Line 1615 in fdc18b3
This is the code that I think should be responsible for doing that:
rust/src/librustc_mir/borrow_check/mod.rs
Lines 1675 to 1679 in fdc18b3
It already looks a little fishy to me; in particular, it is returning
Arbitrary
ifpi1
is a union, but I guess it should be equally true ifpi2
is a union. Anyway, something here seems to be going awry!31 remaining items