grame-cncm / faust

Functional programming language for signal processing and sound synthesis
http://faust.grame.fr
Other
2.58k stars 322 forks source link

Rust backend: mutable reference to mutable static is deprecated #1005

Open bluenote10 opened 7 months ago

bluenote10 commented 7 months ago

Starting with Rust version 1.77 (released a few days ago), there is a new compiler warning related to "mutable reference to mutable static".

Given a simple Faust DSP like

import("stdfaust.lib");

envelope(gate) = gate : en.adsr(0.01, 0.01, 0.3, 0.1);
osci(f) = (os.osc(f) * 0.5 + os.osc(f*2) * 0.25 + os.osc(f*3) * 0.125);
synth(gate, freq) = envelope(gate) * osci(freq);

process = synth;

The code generation will currently produce a pattern like this (omitting everything but the relevant stuff here):

static mut ftbl0GenOscillatorSIG0: [F32; 65536] = [0.0; 65536];

impl FaustDsp for GenOscillator {

    // ...

    fn class_init(sample_rate: i32) {
        let mut sig0: GenOscillatorSIG0 = newGenOscillatorSIG0();
        sig0.instance_initGenOscillatorSIG0(sample_rate);
        sig0.fillGenOscillatorSIG0(65536, unsafe { &mut ftbl0GenOscillatorSIG0 }); // <= problem here
    }

}

This produces the following warning:

warning: creating a mutable reference to mutable static is discouraged
   --> faust/src/gen_oscillator.rs:156:52
    |
156 |         sig0.fillGenOscillatorSIG0(65536, unsafe { &mut ftbl0GenOscillatorSIG0 });
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static
    |
    = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
    = note: this will be a hard error in the 2024 edition
    = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior
    = note: `#[warn(static_mut_refs)]` on by default
help: use `addr_of_mut!` instead to create a raw pointer
    |
156 |         sig0.fillGenOscillatorSIG0(65536, unsafe { addr_of_mut!(ftbl0GenOscillatorSIG0) });
    |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Note however, that this is only a warning for now. In the future it will become a hard error, so just silencing the warning is not an option. A bit more background can be found here:

I haven't looked into it in details, but on first glance this could indeed be a case of "insta-UB", when class_init is called concurrently from different threads.

Considering that this buffer is essentially a static lookup thingy, a thread_local! approach may be the most appropriate solution, but I haven't investigated yet how difficult it would be to incorporate it into the code generation.

sletz commented 7 months ago

OK... PR welcome !