This repository has been archived by the owner on May 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #92 - serde-rs:stack, r=erickt
Add syntex::with_extra_stack helper This is the same workaround from serde-rs/serde#503. I am adding it here because Servo just hit this with quasi_codegen (rust-lang/rust-bindgen#35) and I want to share the code. I will update the serde_codegen implementation to use this too. Unfortunately we can't apply this to `syntex::Registry::expand` in general because rustc overflows its stack trying to decide whether `syntex::Registry` implements Send :panda_face:.
- Loading branch information
Showing
2 changed files
with
66 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use std::env; | ||
use std::ffi::OsStr; | ||
use std::ops::Drop; | ||
use std::thread; | ||
|
||
const STACK_ENV_VAR: &'static str = "RUST_MIN_STACK"; | ||
const EXTRA_STACK: &'static str = "16777216"; // 16 MB | ||
|
||
/// Runs a function in a thread with extra stack space (16 MB or | ||
/// `$RUST_MIN_STACK` if set). | ||
/// | ||
/// The Rust parser uses a lot of stack space so codegen sometimes requires more | ||
/// than is available by default. | ||
/// | ||
/// ```rust,ignore | ||
/// syntex::with_extra_stack(move || { | ||
/// let mut reg = syntex::Registry::new(); | ||
/// reg.add_decorator(/* ... */); | ||
/// reg.expand("", src, dst) | ||
/// }) | ||
/// ``` | ||
/// | ||
/// This function runs with a 16 MB stack by default but a different value can | ||
/// be set by the RUST_MIN_STACK environment variable. | ||
pub fn with_extra_stack<F, T>(f: F) -> T | ||
where F: Send + 'static + FnOnce() -> T, | ||
T: Send + 'static | ||
{ | ||
let _tmp_env = set_if_unset(STACK_ENV_VAR, EXTRA_STACK); | ||
|
||
thread::spawn(f).join().unwrap() | ||
} | ||
|
||
fn set_if_unset<K, V>(k: K, v: V) -> TmpEnv<K> | ||
where K: AsRef<OsStr>, | ||
V: AsRef<OsStr>, | ||
{ | ||
match env::var(&k) { | ||
Ok(_) => TmpEnv::WasAlreadySet, | ||
Err(_) => { | ||
env::set_var(&k, v); | ||
TmpEnv::WasNotSet(k) | ||
} | ||
} | ||
} | ||
|
||
#[must_use] | ||
enum TmpEnv<K> | ||
where K: AsRef<OsStr>, | ||
{ | ||
WasAlreadySet, | ||
WasNotSet(K), | ||
} | ||
|
||
impl<K> Drop for TmpEnv<K> | ||
where K: AsRef<OsStr>, | ||
{ | ||
fn drop(&mut self) { | ||
if let TmpEnv::WasNotSet(ref k) = *self { | ||
env::remove_var(k); | ||
} | ||
} | ||
} |