about summary refs log tree commit diff
path: root/compiler/rustc_interface/src/util.rs
diff options
context:
space:
mode:
authorJubilee Young <workingjubilee@gmail.com>2024-05-19 17:25:25 -0700
committerJubilee Young <workingjubilee@gmail.com>2024-05-19 18:28:14 -0700
commit9985821b2fe20a969b799ec920563170fcc45d8f (patch)
treecb0b0ee7572eb3fafa3e312844d290d6b2db91d0 /compiler/rustc_interface/src/util.rs
parentdef6b99b4a8e1362c9271e39de68e63cacac11ec (diff)
downloadrust-9985821b2fe20a969b799ec920563170fcc45d8f.tar.gz
rust-9985821b2fe20a969b799ec920563170fcc45d8f.zip
defrost RUST_MIN_STACK=ice rustc hello.rs
An earlier commit included the change for a suggestion here.
Unfortunately, it also used unwrap instead of dying properly.
Roll out the ~~rice paper~~ EarlyDiagCtxt before we do anything that
might leave a mess.
Diffstat (limited to 'compiler/rustc_interface/src/util.rs')
-rw-r--r--compiler/rustc_interface/src/util.rs35
1 files changed, 26 insertions, 9 deletions
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index ce4d3825015..f549ae49012 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -51,20 +51,32 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy
 pub static STACK_SIZE: OnceLock<usize> = OnceLock::new();
 pub const DEFAULT_STACK_SIZE: usize = 8 * 1024 * 1024;
 
-fn init_stack_size() -> usize {
+fn init_stack_size(early_dcx: &EarlyDiagCtxt) -> usize {
     // Obey the environment setting or default
     *STACK_SIZE.get_or_init(|| {
         env::var_os("RUST_MIN_STACK")
-            .map(|os_str| os_str.to_string_lossy().into_owned())
-            // ignore if it is set to nothing
-            .filter(|s| s.trim() != "")
-            .map(|s| s.trim().parse::<usize>().unwrap())
+            .as_ref()
+            .map(|os_str| os_str.to_string_lossy())
+            // if someone finds out `export RUST_MIN_STACK=640000` isn't enough stack
+            // they might try to "unset" it by running `RUST_MIN_STACK=  rustc code.rs`
+            // this is wrong, but std would nonetheless "do what they mean", so let's do likewise
+            .filter(|s| !s.trim().is_empty())
+            // rustc is a batch program, so error early on inputs which are unlikely to be intended
+            // so no one thinks we parsed them setting `RUST_MIN_STACK="64 megabytes"`
+            // FIXME: we could accept `RUST_MIN_STACK=64MB`, perhaps?
+            .map(|s| {
+                s.trim().parse::<usize>().unwrap_or_else(|_| {
+                    #[allow(rustc::untranslatable_diagnostic)]
+                    early_dcx.early_fatal("`RUST_MIN_STACK` should be unset or a number of bytes")
+                })
+            })
             // otherwise pick a consistent default
             .unwrap_or(DEFAULT_STACK_SIZE)
     })
 }
 
 fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
+    thread_stack_size: usize,
     edition: Edition,
     sm_inputs: SourceMapInputs,
     f: F,
@@ -75,7 +87,7 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     // the parallel compiler, in particular to ensure there is no accidental
     // sharing of data between the main thread and the compilation thread
     // (which might cause problems for the parallel compiler).
-    let builder = thread::Builder::new().name("rustc".to_string()).stack_size(init_stack_size());
+    let builder = thread::Builder::new().name("rustc".to_string()).stack_size(thread_stack_size);
 
     // We build the session globals and run `f` on the spawned thread, because
     // `SessionGlobals` does not impl `Send` in the non-parallel compiler.
@@ -100,16 +112,19 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
 
 #[cfg(not(parallel_compiler))]
 pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
+    thread_builder_diag: &EarlyDiagCtxt,
     edition: Edition,
     _threads: usize,
     sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
-    run_in_thread_with_globals(edition, sm_inputs, f)
+    let thread_stack_size = init_stack_size(thread_builder_diag);
+    run_in_thread_with_globals(thread_stack_size, edition, sm_inputs, f)
 }
 
 #[cfg(parallel_compiler)]
 pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
+    thread_builder_diag: &EarlyDiagCtxt,
     edition: Edition,
     threads: usize,
     sm_inputs: SourceMapInputs,
@@ -121,10 +136,12 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     use rustc_query_system::query::{break_query_cycles, QueryContext};
     use std::process;
 
+    let thread_stack_size = init_stack_size(thread_builder_diag);
+
     let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());
 
     if !sync::is_dyn_thread_safe() {
-        return run_in_thread_with_globals(edition, sm_inputs, |current_gcx| {
+        return run_in_thread_with_globals(thread_stack_size, edition, sm_inputs, |current_gcx| {
             // Register the thread for use with the `WorkerLocal` type.
             registry.register();
 
@@ -167,7 +184,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
                 })
                 .unwrap();
         })
-        .stack_size(init_stack_size());
+        .stack_size(thread_stack_size);
 
     // We create the session globals on the main thread, then create the thread
     // pool. Upon creation, each worker thread created gets a copy of the