//! returns: 0
//! Standalone repro: writing a record into a static slice clobbers the slice header.

record Entry: Copy {
    a: u32,
    b: u32,
    c: u32,
    d: u32,
    e: u32,
    f: u32,
    g: u32,
    h: u32,
    i: u32,
    j: u32,
    k: u32,
    l: u32,
    m: u32,
    n: u32,
    o: u32,
    p: u32,
    q: u32,
    r: u32,
    s: u32,
    t: u32,
}

record Analyzer: Copy {
    pad0: u32,
    pad1: u32,
    entries: *mut [Entry],
    len: u32,
}

static STORAGE: [Entry; 2] = [
    Entry { a: 0, b: 0, c: 0, d: 0, e: 0, f: 0, g: 0, h: 0, i: 0, j: 0, k: 0, l: 0, m: 0, n: 0, o: 0, p: 0, q: 0, r: 0, s: 0, t: 0 },
    Entry { a: 0, b: 0, c: 0, d: 0, e: 0, f: 0, g: 0, h: 0, i: 0, j: 0, k: 0, l: 0, m: 0, n: 0, o: 0, p: 0, q: 0, r: 0, s: 0, t: 0 },
];
static DEFAULT_ENTRY: Entry = Entry {
    a: 0xAAAA1111,
    b: 0xBBBB2222,
    c: 0xCCCC3333,
    d: 0xDDDD4444,
    e: 0xEEEE5555,
    f: 0x12345601,
    g: 0x12345602,
    h: 0x12345603,
    i: 0x12345604,
    j: 0x12345605,
    k: 0x12345606,
    l: 0x12345607,
    m: 0x12345608,
    n: 0x12345609,
    o: 0x1234560A,
    p: 0x1234560B,
    q: 0x1234560C,
    r: 0x1234560D,
    s: 0x1234560E,
    t: 0x1234560F,
};
static ANALYZER: Analyzer = undefined;

fn fillEntry(out: *mut Entry) {
    set *out = DEFAULT_ENTRY;
}

fn mkEntry() -> Entry {
    return DEFAULT_ENTRY;
}

fn mkOptEntry(ok: bool) -> ?Entry {
    if not ok {
        return nil;
    }
    return mkEntry();
}

fn init(entries: *mut [Entry]) {
    set ANALYZER = Analyzer {
        pad0: 0xDEADAAA0,
        pad1: 0xDEADAAA1,
        entries,
        len: 0,
    };
}

fn add() {
    let idx = ANALYZER.len;
    let entry = mkOptEntry(true) else {
        return;
    };
    set ANALYZER.entries[idx] = entry;
    set ANALYZER.len = idx + 1;
}

fn checkHeader(expected: *[Entry]) -> i32 {
    if ANALYZER.entries.ptr <> expected.ptr or ANALYZER.entries.len <> expected.len {
        // Slice header got clobbered instead of the backing storage.
        return 1;
    }
    if ANALYZER.len <> 1 {
        // Bookkeeping field was overwritten by the bad store.
        return 2;
    }
    assert ANALYZER.pad0 == 0xDEADAAA0 and ANALYZER.pad1 == 0xDEADAAA1;

    let stored = STORAGE[0];
    if stored.a <> 0xAAAA1111 or stored.b <> 0xBBBB2222 or stored.c <> 0xCCCC3333 or stored.d <> 0xDDDD4444 or stored.e <> 0xEEEE5555 or stored.f <> 0x12345601 or stored.j <> 0x12345605 or stored.t <> 0x1234560F {
        // The write never hit the backing buffer.
        return 3;
    }
    return 0;
}

@default fn main() -> i32 {
    let target = &mut STORAGE[..];
    init(target);
    add();
    return checkHeader(target);
}
