@@ -51,20 +51,32 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy
5151pub static STACK_SIZE : OnceLock < usize > = OnceLock :: new ( ) ;
5252pub const DEFAULT_STACK_SIZE : usize = 8 * 1024 * 1024 ;
5353
54- fn init_stack_size ( ) -> usize {
54+ fn init_stack_size ( early_dcx : & EarlyDiagCtxt ) -> usize {
5555 // Obey the environment setting or default
5656 * STACK_SIZE . get_or_init ( || {
5757 env:: var_os ( "RUST_MIN_STACK" )
58- . map ( |os_str| os_str. to_string_lossy ( ) . into_owned ( ) )
59- // ignore if it is set to nothing
60- . filter ( |s| s. trim ( ) != "" )
61- . map ( |s| s. trim ( ) . parse :: < usize > ( ) . unwrap ( ) )
58+ . as_ref ( )
59+ . map ( |os_str| os_str. to_string_lossy ( ) )
60+ // if someone finds out `export RUST_MIN_STACK=640000` isn't enough stack
61+ // they might try to "unset" it by running `RUST_MIN_STACK= rustc code.rs`
62+ // this is wrong, but std would nonetheless "do what they mean", so let's do likewise
63+ . filter ( |s| !s. trim ( ) . is_empty ( ) )
64+ // rustc is a batch program, so error early on inputs which are unlikely to be intended
65+ // so no one thinks we parsed them setting `RUST_MIN_STACK="64 megabytes"`
66+ // FIXME: we could accept `RUST_MIN_STACK=64MB`, perhaps?
67+ . map ( |s| {
68+ s. trim ( ) . parse :: < usize > ( ) . unwrap_or_else ( |_| {
69+ #[ allow( rustc:: untranslatable_diagnostic) ]
70+ early_dcx. early_fatal ( "`RUST_MIN_STACK` should be unset or a number of bytes" )
71+ } )
72+ } )
6273 // otherwise pick a consistent default
6374 . unwrap_or ( DEFAULT_STACK_SIZE )
6475 } )
6576}
6677
6778fn run_in_thread_with_globals < F : FnOnce ( CurrentGcx ) -> R + Send , R : Send > (
79+ thread_stack_size : usize ,
6880 edition : Edition ,
6981 sm_inputs : SourceMapInputs ,
7082 f : F ,
@@ -75,7 +87,7 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
7587 // the parallel compiler, in particular to ensure there is no accidental
7688 // sharing of data between the main thread and the compilation thread
7789 // (which might cause problems for the parallel compiler).
78- let builder = thread:: Builder :: new ( ) . name ( "rustc" . to_string ( ) ) . stack_size ( init_stack_size ( ) ) ;
90+ let builder = thread:: Builder :: new ( ) . name ( "rustc" . to_string ( ) ) . stack_size ( thread_stack_size ) ;
7991
8092 // We build the session globals and run `f` on the spawned thread, because
8193 // `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>(
100112
101113#[ cfg( not( parallel_compiler) ) ]
102114pub ( crate ) fn run_in_thread_pool_with_globals < F : FnOnce ( CurrentGcx ) -> R + Send , R : Send > (
115+ thread_builder_diag : & EarlyDiagCtxt ,
103116 edition : Edition ,
104117 _threads : usize ,
105118 sm_inputs : SourceMapInputs ,
106119 f : F ,
107120) -> R {
108- run_in_thread_with_globals ( edition, sm_inputs, f)
121+ let thread_stack_size = init_stack_size ( thread_builder_diag) ;
122+ run_in_thread_with_globals ( thread_stack_size, edition, sm_inputs, f)
109123}
110124
111125#[ cfg( parallel_compiler) ]
112126pub ( crate ) fn run_in_thread_pool_with_globals < F : FnOnce ( CurrentGcx ) -> R + Send , R : Send > (
127+ thread_builder_diag : & EarlyDiagCtxt ,
113128 edition : Edition ,
114129 threads : usize ,
115130 sm_inputs : SourceMapInputs ,
@@ -121,10 +136,12 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
121136 use rustc_query_system:: query:: { break_query_cycles, QueryContext } ;
122137 use std:: process;
123138
139+ let thread_stack_size = init_stack_size ( thread_builder_diag) ;
140+
124141 let registry = sync:: Registry :: new ( std:: num:: NonZero :: new ( threads) . unwrap ( ) ) ;
125142
126143 if !sync:: is_dyn_thread_safe ( ) {
127- return run_in_thread_with_globals ( edition, sm_inputs, |current_gcx| {
144+ return run_in_thread_with_globals ( thread_stack_size , edition, sm_inputs, |current_gcx| {
128145 // Register the thread for use with the `WorkerLocal` type.
129146 registry. register ( ) ;
130147
@@ -167,7 +184,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
167184 } )
168185 . unwrap ( ) ;
169186 } )
170- . stack_size ( init_stack_size ( ) ) ;
187+ . stack_size ( thread_stack_size ) ;
171188
172189 // We create the session globals on the main thread, then create the thread
173190 // pool. Upon creation, each worker thread created gets a copy of the
0 commit comments