@@ -157,10 +157,14 @@ impl ProjectCompiler {
157
157
{
158
158
self . project_root = project. root ( ) . to_path_buf ( ) ;
159
159
160
- // TODO: Avoid process::exit
160
+ // TODO: Avoid using std::process::exit(0).
161
+ // Replacing this with a return (e.g., Ok(ProjectCompileOutput::default())) would be more
162
+ // idiomatic, but it currently requires a `Default` bound on `C::Language`, which
163
+ // breaks compatibility with downstream crates like `foundry-cli`. This would need a
164
+ // broader refactor across the call chain. Leaving it as-is for now until a larger
165
+ // refactor is feasible.
161
166
if !project. paths . has_input_files ( ) && self . files . is_empty ( ) {
162
167
sh_println ! ( "Nothing to compile" ) ?;
163
- // nothing to do here
164
168
std:: process:: exit ( 0 ) ;
165
169
}
166
170
@@ -204,7 +208,7 @@ impl ProjectCompiler {
204
208
let quiet = self . quiet . unwrap_or ( false ) ;
205
209
let bail = self . bail . unwrap_or ( true ) ;
206
210
207
- let output = with_compilation_reporter ( self . quiet . unwrap_or ( false ) , || {
211
+ let output = with_compilation_reporter ( quiet, || {
208
212
tracing:: debug!( "compiling project" ) ;
209
213
210
214
let timer = Instant :: now ( ) ;
@@ -229,7 +233,7 @@ impl ProjectCompiler {
229
233
}
230
234
}
231
235
232
- self . handle_output ( & output) ;
236
+ self . handle_output ( & output) ? ;
233
237
}
234
238
235
239
Ok ( output)
@@ -239,7 +243,7 @@ impl ProjectCompiler {
239
243
fn handle_output < C : Compiler < CompilerContract = Contract > > (
240
244
& self ,
241
245
output : & ProjectCompileOutput < C > ,
242
- ) {
246
+ ) -> Result < ( ) > {
243
247
let print_names = self . print_names . unwrap_or ( false ) ;
244
248
let print_sizes = self . print_sizes . unwrap_or ( false ) ;
245
249
@@ -251,17 +255,17 @@ impl ProjectCompiler {
251
255
}
252
256
253
257
if shell:: is_json ( ) {
254
- let _ = sh_println ! ( "{}" , serde_json:: to_string( & artifacts) . unwrap( ) ) ;
258
+ sh_println ! ( "{}" , serde_json:: to_string( & artifacts) . unwrap( ) ) ? ;
255
259
} else {
256
260
for ( version, names) in artifacts {
257
- let _ = sh_println ! (
261
+ sh_println ! (
258
262
" compiler version: {}.{}.{}" ,
259
263
version. major,
260
264
version. minor,
261
265
version. patch
262
- ) ;
266
+ ) ? ;
263
267
for name in names {
264
- let _ = sh_println ! ( " - {name}" ) ;
268
+ sh_println ! ( " - {name}" ) ? ;
265
269
}
266
270
}
267
271
}
@@ -270,7 +274,7 @@ impl ProjectCompiler {
270
274
if print_sizes {
271
275
// add extra newline if names were already printed
272
276
if print_names && !shell:: is_json ( ) {
273
- let _ = sh_println ! ( ) ;
277
+ sh_println ! ( ) ? ;
274
278
}
275
279
276
280
let mut size_report =
@@ -317,19 +321,22 @@ impl ProjectCompiler {
317
321
}
318
322
}
319
323
320
- let _ = sh_println ! ( "{size_report}" ) ;
321
-
322
- // TODO: avoid process::exit
323
- // exit with error if any contract exceeds the size limit, excluding test contracts.
324
- if size_report. exceeds_runtime_size_limit ( ) {
325
- std:: process:: exit ( 1 ) ;
326
- }
324
+ sh_println ! ( "{size_report}" ) ?;
327
325
326
+ eyre:: ensure!(
327
+ !size_report. exceeds_runtime_size_limit( ) ,
328
+ "some contracts exceed the runtime size limit \
329
+ (EIP-170: {CONTRACT_RUNTIME_SIZE_LIMIT} bytes)"
330
+ ) ;
328
331
// Check size limits only if not ignoring EIP-3860
329
- if !self . ignore_eip_3860 && size_report. exceeds_initcode_size_limit ( ) {
330
- std:: process:: exit ( 1 ) ;
331
- }
332
+ eyre:: ensure!(
333
+ self . ignore_eip_3860 || !size_report. exceeds_initcode_size_limit( ) ,
334
+ "some contracts exceed the initcode size limit \
335
+ (EIP-3860: {CONTRACT_INITCODE_SIZE_LIMIT} bytes)"
336
+ ) ;
332
337
}
338
+
339
+ Ok ( ( ) )
333
340
}
334
341
}
335
342
0 commit comments