@@ -1393,54 +1393,69 @@ impl Compiler {
13931393 body : & [ ast:: Stmt ] ,
13941394 is_async : bool ,
13951395 ) -> CompileResult < ( ) > {
1396- let end_blocks = items
1397- . iter ( )
1398- . map ( |item| {
1399- let end_block = self . new_block ( ) ;
1400- self . compile_expression ( & item. context_expr ) ?;
1396+ let with_location = self . current_source_location ;
14011397
1402- if is_async {
1403- self . emit ( Instruction :: BeforeAsyncWith ) ;
1404- self . emit ( Instruction :: GetAwaitable ) ;
1405- self . emit_constant ( ConstantData :: None ) ;
1406- self . emit ( Instruction :: YieldFrom ) ;
1407- self . emit ( Instruction :: SetupAsyncWith { end : end_block } ) ;
1408- } else {
1409- self . emit ( Instruction :: SetupWith { end : end_block } ) ;
1410- }
1398+ let ( item, items) = if let Some ( parts) = items. split_first ( ) {
1399+ parts
1400+ } else {
1401+ return Err ( self . error ( CompileErrorType :: EmptyWithItems ) ) ;
1402+ } ;
14111403
1412- match & item. optional_vars {
1413- Some ( var) => {
1414- self . compile_store ( var) ?;
1415- }
1416- None => {
1417- self . emit ( Instruction :: Pop ) ;
1418- }
1404+ let final_block = {
1405+ let final_block = self . new_block ( ) ;
1406+ self . compile_expression ( & item. context_expr ) ?;
1407+
1408+ self . set_source_location ( with_location) ;
1409+ if is_async {
1410+ self . emit ( Instruction :: BeforeAsyncWith ) ;
1411+ self . emit ( Instruction :: GetAwaitable ) ;
1412+ self . emit_constant ( ConstantData :: None ) ;
1413+ self . emit ( Instruction :: YieldFrom ) ;
1414+ self . emit ( Instruction :: SetupAsyncWith { end : final_block } ) ;
1415+ } else {
1416+ self . emit ( Instruction :: SetupWith { end : final_block } ) ;
1417+ }
1418+
1419+ match & item. optional_vars {
1420+ Some ( var) => {
1421+ self . set_source_location ( var. location ) ;
1422+ self . compile_store ( var) ?;
1423+ }
1424+ None => {
1425+ self . emit ( Instruction :: Pop ) ;
14191426 }
1420- Ok ( end_block )
1421- } )
1422- . collect :: < CompileResult < Vec < _ > > > ( ) ? ;
1427+ }
1428+ final_block
1429+ } ;
14231430
1424- self . compile_statements ( body) ?;
1431+ if items. is_empty ( ) {
1432+ if body. is_empty ( ) {
1433+ return Err ( self . error ( CompileErrorType :: EmptyWithBody ) ) ;
1434+ }
1435+ self . compile_statements ( body) ?;
1436+ } else {
1437+ self . set_source_location ( with_location) ;
1438+ self . compile_with ( items, body, is_async) ?;
1439+ }
14251440
14261441 // sort of "stack up" the layers of with blocks:
14271442 // with a, b: body -> start_with(a) start_with(b) body() end_with(b) end_with(a)
1428- for end_block in end_blocks. into_iter ( ) . rev ( ) {
1429- self . emit ( Instruction :: PopBlock ) ;
1430- self . emit ( Instruction :: EnterFinally ) ;
1443+ self . set_source_location ( with_location) ;
1444+ self . emit ( Instruction :: PopBlock ) ;
14311445
1432- self . switch_to_block ( end_block) ;
1433- self . emit ( Instruction :: WithCleanupStart ) ;
1446+ self . emit ( Instruction :: EnterFinally ) ;
14341447
1435- if is_async {
1436- self . emit ( Instruction :: GetAwaitable ) ;
1437- self . emit_constant ( ConstantData :: None ) ;
1438- self . emit ( Instruction :: YieldFrom ) ;
1439- }
1448+ self . switch_to_block ( final_block) ;
1449+ self . emit ( Instruction :: WithCleanupStart ) ;
14401450
1441- self . emit ( Instruction :: WithCleanupFinish ) ;
1451+ if is_async {
1452+ self . emit ( Instruction :: GetAwaitable ) ;
1453+ self . emit_constant ( ConstantData :: None ) ;
1454+ self . emit ( Instruction :: YieldFrom ) ;
14421455 }
14431456
1457+ self . emit ( Instruction :: WithCleanupFinish ) ;
1458+
14441459 Ok ( ( ) )
14451460 }
14461461
0 commit comments