Skip to content

Commit

Permalink
Auto merge of #63831 - eddyb:proc-macro-statecheck, r=<try>
Browse files Browse the repository at this point in the history
[WIP] rustc_mir: disallow global mutable state in proc macros.

Along the lines of #63809, this PR attempts to get rid of the main (or only?) place `proc_macro` handles could be leaked to, *and* further disallow/discourage sharing (other) state between invocations.

The approach of banning (interior-)mutable `static`s was most recently mentioned in #63804 (comment), but it's likely been brought up several times, we just never tried it.
(Note that this is not foolproof: one would have to scan all dependencies for such `static`s, modulo `proc_macro`/`std`, and even then it's possible there would be a lot of false positives)

So this is mostly for a check-only crater run, to see what (if anything) breaks.
  • Loading branch information
bors committed Aug 23, 2019
2 parents f834695 + ee8492f commit 8c9c32a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,19 @@ impl MirPass for QualifyAndPromoteConstants {
}
}

// 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");
}
}
}

// Statics must be Sync.
if mode == Mode::Static {
// `#[thread_local]` statics don't have to be `Sync`.
Expand Down
19 changes: 19 additions & 0 deletions src/test/ui/proc-macro/global-mut-state.rs
Original file line number Diff line number Diff line change
@@ -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<String> = Cell::new(String::new()));
//~^ ERROR mutable global state in a proc-macro

static FROZEN: &str = "snow";
22 changes: 22 additions & 0 deletions src/test/ui/proc-macro/global-mut-state.stderr
Original file line number Diff line number Diff line change
@@ -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<String> = 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

0 comments on commit 8c9c32a

Please sign in to comment.