@@ -51,20 +51,32 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy
51
51
pub static STACK_SIZE : OnceLock < usize > = OnceLock :: new ( ) ;
52
52
pub const DEFAULT_STACK_SIZE : usize = 8 * 1024 * 1024 ;
53
53
54
- fn init_stack_size ( ) -> usize {
54
+ fn init_stack_size ( early_dcx : & EarlyDiagCtxt ) -> usize {
55
55
// Obey the environment setting or default
56
56
* STACK_SIZE . get_or_init ( || {
57
57
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
+ } )
62
73
// otherwise pick a consistent default
63
74
. unwrap_or ( DEFAULT_STACK_SIZE )
64
75
} )
65
76
}
66
77
67
78
fn run_in_thread_with_globals < F : FnOnce ( CurrentGcx ) -> R + Send , R : Send > (
79
+ thread_stack_size : usize ,
68
80
edition : Edition ,
69
81
sm_inputs : SourceMapInputs ,
70
82
f : F ,
@@ -75,7 +87,7 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
75
87
// the parallel compiler, in particular to ensure there is no accidental
76
88
// sharing of data between the main thread and the compilation thread
77
89
// (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 ) ;
79
91
80
92
// We build the session globals and run `f` on the spawned thread, because
81
93
// `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>(
100
112
101
113
#[ cfg( not( parallel_compiler) ) ]
102
114
pub ( crate ) fn run_in_thread_pool_with_globals < F : FnOnce ( CurrentGcx ) -> R + Send , R : Send > (
115
+ thread_builder_diag : & EarlyDiagCtxt ,
103
116
edition : Edition ,
104
117
_threads : usize ,
105
118
sm_inputs : SourceMapInputs ,
106
119
f : F ,
107
120
) -> 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)
109
123
}
110
124
111
125
#[ cfg( parallel_compiler) ]
112
126
pub ( crate ) fn run_in_thread_pool_with_globals < F : FnOnce ( CurrentGcx ) -> R + Send , R : Send > (
127
+ thread_builder_diag : & EarlyDiagCtxt ,
113
128
edition : Edition ,
114
129
threads : usize ,
115
130
sm_inputs : SourceMapInputs ,
@@ -121,10 +136,12 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
121
136
use rustc_query_system:: query:: { break_query_cycles, QueryContext } ;
122
137
use std:: process;
123
138
139
+ let thread_stack_size = init_stack_size ( thread_builder_diag) ;
140
+
124
141
let registry = sync:: Registry :: new ( std:: num:: NonZero :: new ( threads) . unwrap ( ) ) ;
125
142
126
143
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| {
128
145
// Register the thread for use with the `WorkerLocal` type.
129
146
registry. register ( ) ;
130
147
@@ -167,7 +184,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
167
184
} )
168
185
. unwrap ( ) ;
169
186
} )
170
- . stack_size ( init_stack_size ( ) ) ;
187
+ . stack_size ( thread_stack_size ) ;
171
188
172
189
// We create the session globals on the main thread, then create the thread
173
190
// pool. Upon creation, each worker thread created gets a copy of the
0 commit comments