Closed
Description
This code should not compile:
demo code courtesy of niko's comment below.
struct Foo { n0: i32, n1: i32 }
fn leak_1_brk() -> Foo {
let ret;
loop {
ret = Foo { n0: { break }, n1: 22 };
}
// (`ret` is still uninitialized here!)
ret
}
fn main() { }
Original report:
I was making regression tests for #21486 and ran into this, though @nikomatsakis has pointed out that it is not specific to FRU.
Test case 1:
use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT};
#[derive(Debug)]
struct Noisy(u8);
impl Drop for Noisy {
fn drop(&mut self) {
// println!("splat #{}", self.0);
event(self.0);
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct Foo { n0: Noisy, n1: Noisy }
impl Foo {
fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) }
}
fn leak_1_brk() -> Foo {
let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
let ret;
loop {
ret = Foo { n0: { break }, .._old_foo };
}
// ret has not been initialized!!!!!
ret
}
pub fn main() {
reset_log();
// Note: there's not much that's reasonable to expect here...
let value = leak_1_brk().vals();
assert_eq!(0x01_02, event_log());
assert_eq!(value, (1,2));
}
static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
fn reset_log() {
LOG.store(0, Ordering::SeqCst);
}
fn event_log() -> usize {
LOG.load(Ordering::SeqCst)
}
fn event(tag: u8) {
let old_log = LOG.load(Ordering::SeqCst);
let new_log = (old_log << 8) + tag as usize;
LOG.store(new_log, Ordering::SeqCst);
}
Test case 2:
use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT};
#[derive(Debug)]
struct Noisy(u8);
impl Drop for Noisy {
fn drop(&mut self) {
// println!("splat #{}", self.0);
event(self.0);
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct Foo { n0: Noisy, n1: Noisy }
impl Foo {
fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) }
}
fn leak_1_brk() -> Foo {
let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
let ret;
loop {
ret = Foo { n0: { break }, n1: { break } };
}
// !!!!!
ret
}
pub fn main() {
reset_log();
// Note: there's not much that's reasonable to expect here...
assert_eq!(leak_1_brk().vals(), (1,2));
assert_eq!(0x01_02, event_log());
}
static LOG: AtomicUsize = ATOMIC_USIZE_INIT;
fn reset_log() {
LOG.store(0, Ordering::SeqCst);
}
fn event_log() -> usize {
LOG.load(Ordering::SeqCst)
}
fn event(tag: u8) {
let old_log = LOG.load(Ordering::SeqCst);
let new_log = (old_log << 8) + tag as usize;
LOG.store(new_log, Ordering::SeqCst);
}