Skip to content

Commit 12ceb96

Browse files
committed
cleaner panic output
Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
1 parent 974c54e commit 12ceb96

4 files changed

Lines changed: 88 additions & 22 deletions

File tree

‎compiler/codegen/src/compile.rs‎

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ use rustpython_compiler_core::{
4242
use rustpython_compiler_source::SourceCode;
4343
// use rustpython_parser_core::source_code::{LineNumber, SourceLocation};
4444
use std::borrow::Cow;
45+
use crate::error::InternalError;
4546

47+
pub(crate) type InternalResult<T> = Result<T, InternalError>;
4648
type CompileResult<T> = Result<T, CodegenError>;
4749

4850
#[derive(PartialEq, Eq, Clone, Copy)]
@@ -210,6 +212,43 @@ macro_rules! emit {
210212
};
211213
}
212214

215+
fn print_location(zelf: &mut Compiler) {
216+
let start = zelf.source_code.source_location(zelf.current_source_range.start());
217+
let end = zelf.source_code.source_location(zelf.current_source_range.end());
218+
eprintln!("LOCATION: {} from {}:{} to {}:{}", zelf.source_code.path.to_owned(), start.row, start.column, end.row, end.column);
219+
}
220+
221+
/// Better traceback for internal error
222+
fn unwrap_internal<T>(zelf: &mut Compiler, r: InternalResult<T>) -> T {
223+
if let Err(r_err) = r {
224+
eprintln!("=== CODEGEN PANIC INFO ===");
225+
eprintln!("This IS an internal error: {}", r_err);
226+
print_location(zelf);
227+
eprintln!("=== END PANIC INFO ===");
228+
}
229+
r.unwrap()
230+
}
231+
232+
fn compiler_unwrap_option<T>(zelf: &mut Compiler, o: Option<T>) -> T {
233+
if let None = o {
234+
eprintln!("=== CODEGEN PANIC INFO ===");
235+
eprintln!("This IS an internal error, an option was unwrapped during codegen");
236+
print_location(zelf);
237+
eprintln!("=== END PANIC INFO ===");
238+
}
239+
o.unwrap()
240+
}
241+
242+
fn compiler_result_unwrap<T, E>(zelf: &mut Compiler, result: Result<T, E>) -> T {
243+
if let Err(r_err) = r {
244+
eprintln!("=== CODEGEN PANIC INFO ===");
245+
eprintln!("This IS an internal error, an result was unwrapped during codegen");
246+
print_location(zelf);
247+
eprintln!("=== END PANIC INFO ===");
248+
}
249+
r.unwrap()
250+
}
251+
213252
/// The pattern context holds information about captured names and jump targets.
214253
#[derive(Clone)]
215254
pub struct PatternContext {
@@ -372,9 +411,8 @@ impl Compiler<'_> {
372411
fn pop_code_object(&mut self) -> CodeObject {
373412
let table = self.pop_symbol_table();
374413
assert!(table.sub_tables.is_empty());
375-
self.code_stack
376-
.pop()
377-
.unwrap()
414+
unwrap_internal(self, self.code_stack
415+
.pop())
378416
.finalize_code(self.opts.optimize)
379417
}
380418

@@ -482,7 +520,7 @@ impl Compiler<'_> {
482520
self.current_block().instructions.pop(); // pop Instruction::Pop
483521
}
484522
Stmt::FunctionDef(_) | Stmt::ClassDef(_) => {
485-
let store_inst = self.current_block().instructions.pop().unwrap(); // pop Instruction::Store
523+
let store_inst = compiler_unwrap_option(zelf, self.current_block().instructions.pop()); // pop Instruction::Store
486524
emit!(self, Instruction::Duplicate);
487525
self.current_block().instructions.push(store_inst);
488526
}
@@ -540,9 +578,9 @@ impl Compiler<'_> {
540578
self.check_forbidden_name(&name, usage)?;
541579

542580
let symbol_table = self.symbol_table_stack.last().unwrap();
543-
let symbol = symbol_table.lookup(name.as_ref()).unwrap_or_else(||
544-
unreachable!("the symbol '{name}' should be present in the symbol table, even when it is undefined in python."),
545-
);
581+
let symbol = unwrap_internal(symbol_table.lookup(name.as_ref()).ok_or_else(||
582+
InternalError::MissingSymbol(name.to_owned())
583+
));
546584
let info = self.code_stack.last_mut().unwrap();
547585
let mut cache = &mut info.name_cache;
548586
enum NameOpType {
@@ -1476,12 +1514,9 @@ impl Compiler<'_> {
14761514
}
14771515
for var in &*code.freevars {
14781516
let table = self.symbol_table_stack.last().unwrap();
1479-
let symbol = table.lookup(var).unwrap_or_else(|| {
1480-
panic!(
1481-
"couldn't look up var {} in {} in {}",
1482-
var, code.obj_name, self.source_code.path
1483-
)
1484-
});
1517+
let symbol = unwrap_internal(table.lookup(var).ok_or_else(|| {
1518+
InternalError::MissingSymbol(var)
1519+
}));
14851520
let parent_code = self.code_stack.last().unwrap();
14861521
let vars = match symbol.scope {
14871522
SymbolScope::Free => &parent_code.freevar_cache,
@@ -1564,9 +1599,7 @@ impl Compiler<'_> {
15641599

15651600
// Check if the class is declared global
15661601
let symbol_table = self.symbol_table_stack.last().unwrap();
1567-
let symbol = symbol_table.lookup(name.as_ref()).expect(
1568-
"The symbol must be present in the symbol table, even when it is undefined in python.",
1569-
);
1602+
let symbol = unwrap_internal(symbol_table.lookup(name.as_ref()).ok_or_else(|| Err(InternalError::MissingSymbol(name.to_owned()))));
15701603
let mut global_path_prefix = Vec::new();
15711604
if symbol.scope == SymbolScope::GlobalExplicit {
15721605
global_path_prefix.append(&mut self.qualified_path);

‎compiler/codegen/src/error.rs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@ impl fmt::Display for CodegenError {
3434
}
3535
}
3636

37+
#[derive(Debug)]
38+
#[non_exhaustive]
39+
pub enum InternalError {
40+
StackOverflow,
41+
StackUnderflow,
42+
MissingSymbol(String),
43+
}
44+
45+
impl Display for InternalError {
46+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47+
match self {
48+
Self::StackOverflow => write!(f, "stack overflow"),
49+
Self::StackUnderflow => write!(f, "stack underflow"),
50+
Self::MissingSymbol(s) => write!(f, "The symbol '{s}' must be present in the symbol table, even when it is undefined in python.")
51+
}
52+
}
53+
}
54+
3755
#[derive(Debug)]
3856
#[non_exhaustive]
3957
pub enum CodegenErrorType {

‎compiler/codegen/src/ir.rs‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use ruff_source_file::{OneIndexed, SourceLocation};
55
use rustpython_compiler_core::bytecode::{
66
CodeFlags, CodeObject, CodeUnit, ConstantData, InstrDisplayContext, Instruction, Label, OpArg,
77
};
8+
use crate::error::InternalError;
89
// use rustpython_parser_core::source_code::{LineNumber, SourceLocation};
910

1011
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -82,12 +83,12 @@ pub struct CodeInfo {
8283
pub freevar_cache: IndexSet<String>,
8384
}
8485
impl CodeInfo {
85-
pub fn finalize_code(mut self, optimize: u8) -> CodeObject {
86+
pub fn finalize_code(mut self, optimize: u8) -> crate::InternalResult<CodeObject> {
8687
if optimize > 0 {
8788
self.dce();
8889
}
8990

90-
let max_stackdepth = self.max_stackdepth();
91+
let max_stackdepth = self.max_stackdepth()?;
9192
let cell2arg = self.cell2arg();
9293

9394
let CodeInfo {
@@ -219,7 +220,7 @@ impl CodeInfo {
219220
}
220221
}
221222

222-
fn max_stackdepth(&self) -> u32 {
223+
fn max_stackdepth(&self) -> crate::InternalResult<u32> {
223224
let mut maxdepth = 0u32;
224225
let mut stack = Vec::with_capacity(self.blocks.len());
225226
let mut start_depths = vec![u32::MAX; self.blocks.len()];
@@ -247,7 +248,13 @@ impl CodeInfo {
247248
if effect < 0 && depth < effect.unsigned_abs() {
248249
panic!("The stack will underflow at {depth} with {effect} effect on {instr:?}");
249250
}
250-
let new_depth = depth.checked_add_signed(effect).unwrap();
251+
let new_depth = depth.checked_add_signed(effect).ok_or_else(|| {
252+
if effect < 0 {
253+
InternalError::StackUnderflow
254+
} else {
255+
InternalError::StackOverflow
256+
}
257+
})?;
251258
if DEBUG {
252259
eprintln!("{new_depth}");
253260
}
@@ -264,7 +271,13 @@ impl CodeInfo {
264271
)
265272
{
266273
let effect = instr.stack_effect(ins.arg, true);
267-
let target_depth = depth.checked_add_signed(effect).unwrap();
274+
let target_depth = depth.checked_add_signed(effect).ok_or_else(|| {
275+
if effect < 0 {
276+
InternalError::StackUnderflow
277+
} else {
278+
InternalError::StackOverflow
279+
}
280+
})?;
268281
if target_depth > maxdepth {
269282
maxdepth = target_depth
270283
}
@@ -280,7 +293,7 @@ impl CodeInfo {
280293
if DEBUG {
281294
eprintln!("DONE: {maxdepth}");
282295
}
283-
maxdepth
296+
Ok(maxdepth)
284297
}
285298
}
286299

‎compiler/codegen/src/lib.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ mod unparse;
1818
pub use compile::CompileOpts;
1919
use ruff_python_ast::Expr;
2020

21+
pub(crate) use compile::InternalResult;
22+
2123
pub trait ToPythonName {
2224
/// Returns a short name for the node suitable for use in error messages.
2325
fn python_name(&self) -> &'static str;

0 commit comments

Comments
 (0)