Static mut refs "safely"

I'm currently trying to add magic bitboards like in Stockfish, where the attack/magic lists are stored in what would effectively be static mut constructs. These are only mutated in one function, which should in theory be run before anything comes close to looking at them. I start to get warnings about static_mut_refs and have been considering other constructs like Cell, although then I get complaints about them not being Sync. Because the tables are mutated incrementally, it doesn't seem feasible to use something like OnceCell.

Is it perfectly fine to go through the hassle of &raw mut MAGIC_TABLE since I know for a fact they can't (won't?) be accessed mutably ever which would not violate the aliasing rules as I understand them?

It also seems unwieldy to initialize them non-statically, but I guess that isn't totally out of the question, it would just be a headache trying to figure out how to pass them seamlessly to the attack generation functions dependent on if the feature flag is enabled.

Make the initialization const and then you can initialize a non-mut static using that.

In the Stockfish code they are computed just once in init_magics.

Without doing nightly (to get const traits), since my Bitboard struct is just a wrapper around a u64, is there a feasible way without unwrapping/wrapping them constantly to get around the fact that the bitwise operations (and shifting, since that masking is built in at the moment) are not const?

This does seem like the best way though. And yeah, they're only initiated in init_magics that's why I figured aliasing rules would be able to be avoided. I'll think about this a bit, thank you!

Edit: by incrementally I meant that individual entries are altered, not the whole list being replaced (so individual Cell stuff would get rough)

Bitwise operations and shifts are const. If you mean on Bitboard: you can implement const versions as needed:

impl Bitboard {
    const fn bitand(self, other: Self) -> Self { ... }
}

Okay. I'll rewrite all the Bitand<Bitboard> traits etc. into ones based off const-viable internal methods so both can be used. :+1:

If tczajka or anyone stumbling upon this in the future sees: Since the magic and attack tables are separate but both initialized bit-by-bit alongside each other, what's the best way to const-initialize both?

An example:

pub struct Tables {
    a: [u32; 10],
    b: [u32; 10],
}

pub static TABLES: Tables = compute_tables();

const fn compute_tables() -> Tables {
    let mut tables = Tables {
        a: [0; 10],
        b: [0; 10],
    };
    let mut i = 1;
    while i != 10 {
        tables.a[i] = tables.b[i-1] + 1;
        tables.b[i] = tables.a[i-1] * 2;
        i += 1;
    }
    tables
}