diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 32b49ee942300..01754b4dda76a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1648,6 +1648,19 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { remove_drop_and_storage_dead_on_promoted_locals(body, promoted_temps); } + // HACK(eddyb) try to prevent global mutable state in proc macros. + // (this is not perfect and could also have false positives) + if mode == Mode::Static || mode == Mode::StaticMut { + use rustc::session::config::CrateType; + if tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro) { + let ty = body.return_ty(); + let param_env = ty::ParamEnv::empty(); + if mode == Mode::StaticMut || !ty.is_freeze(tcx, param_env, DUMMY_SP) { + tcx.sess.span_err(body.span, "mutable global state in a proc-macro"); + } + } + } + if mode == Mode::Static && !tcx.has_attr(def_id, sym::thread_local) { // `static`s (not `static mut`s) which are not `#[thread_local]` must be `Sync`. check_static_is_sync(tcx, body, hir_id); diff --git a/src/test/ui/proc-macro/global-mut-state.rs b/src/test/ui/proc-macro/global-mut-state.rs new file mode 100644 index 0000000000000..f984ceec93199 --- /dev/null +++ b/src/test/ui/proc-macro/global-mut-state.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![allow(warnings)] + +use std::cell::Cell; +use std::sync::atomic::AtomicBool; + +static mut FOO: u8 = 0; +//~^ ERROR mutable global state in a proc-macro + +static BAR: AtomicBool = AtomicBool::new(false); +//~^ ERROR mutable global state in a proc-macro + +thread_local!(static BAZ: Cell = Cell::new(String::new())); +//~^ ERROR mutable global state in a proc-macro + +static FROZEN: &str = "snow"; diff --git a/src/test/ui/proc-macro/global-mut-state.stderr b/src/test/ui/proc-macro/global-mut-state.stderr new file mode 100644 index 0000000000000..e019b7e17f69f --- /dev/null +++ b/src/test/ui/proc-macro/global-mut-state.stderr @@ -0,0 +1,22 @@ +error: mutable global state in a proc-macro + --> $DIR/global-mut-state.rs:10:1 + | +LL | static mut FOO: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: mutable global state in a proc-macro + --> $DIR/global-mut-state.rs:13:1 + | +LL | static BAR: AtomicBool = AtomicBool::new(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: mutable global state in a proc-macro + --> $DIR/global-mut-state.rs:16:1 + | +LL | thread_local!(static BAZ: Cell = Cell::new(String::new())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 3 previous errors +