Skip to content

Commit 8c9c32a

Browse files
committed
Auto merge of #63831 - eddyb:proc-macro-statecheck, r=<try>
[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.
2 parents f834695 + ee8492f commit 8c9c32a

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

src/librustc_mir/transform/qualify_consts.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,19 @@ impl MirPass for QualifyAndPromoteConstants {
17231723
}
17241724
}
17251725

1726+
// HACK(eddyb) try to prevent global mutable state in proc macros.
1727+
// (this is not perfect and could also have false positives)
1728+
if mode == Mode::Static || mode == Mode::StaticMut {
1729+
use rustc::session::config::CrateType;
1730+
if tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro) {
1731+
let ty = body.return_ty();
1732+
let param_env = ty::ParamEnv::empty();
1733+
if mode == Mode::StaticMut || !ty.is_freeze(tcx, param_env, DUMMY_SP) {
1734+
tcx.sess.span_err(body.span, "mutable global state in a proc-macro");
1735+
}
1736+
}
1737+
}
1738+
17261739
// Statics must be Sync.
17271740
if mode == Mode::Static {
17281741
// `#[thread_local]` statics don't have to be `Sync`.
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![crate_type = "proc-macro"]
5+
#![allow(warnings)]
6+
7+
use std::cell::Cell;
8+
use std::sync::atomic::AtomicBool;
9+
10+
static mut FOO: u8 = 0;
11+
//~^ ERROR mutable global state in a proc-macro
12+
13+
static BAR: AtomicBool = AtomicBool::new(false);
14+
//~^ ERROR mutable global state in a proc-macro
15+
16+
thread_local!(static BAZ: Cell<String> = Cell::new(String::new()));
17+
//~^ ERROR mutable global state in a proc-macro
18+
19+
static FROZEN: &str = "snow";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: mutable global state in a proc-macro
2+
--> $DIR/global-mut-state.rs:10:1
3+
|
4+
LL | static mut FOO: u8 = 0;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: mutable global state in a proc-macro
8+
--> $DIR/global-mut-state.rs:13:1
9+
|
10+
LL | static BAR: AtomicBool = AtomicBool::new(false);
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: mutable global state in a proc-macro
14+
--> $DIR/global-mut-state.rs:16:1
15+
|
16+
LL | thread_local!(static BAZ: Cell<String> = Cell::new(String::new()));
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
|
19+
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
20+
21+
error: aborting due to 3 previous errors
22+

0 commit comments

Comments
 (0)