Skip to main content

rustpython_codegen/
error.rs

1use alloc::fmt;
2use core::fmt::Display;
3use rustpython_compiler_core::SourceLocation;
4use thiserror::Error;
5
6// pub type CodegenError = rustpython_parser_core::source_code::LocatedError<CodegenErrorType>;
7
8#[derive(Error, Debug)]
9pub struct CodegenError {
10    pub location: Option<SourceLocation>,
11    pub end_location: Option<SourceLocation>,
12    #[source]
13    pub error: CodegenErrorType,
14    pub source_path: String,
15}
16
17impl fmt::Display for CodegenError {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        // TODO:
20        self.error.fmt(f)
21    }
22}
23
24#[derive(Debug)]
25#[non_exhaustive]
26pub enum InternalError {
27    StackUnderflow,
28    InconsistentStackDepth,
29    InvalidStackEffect,
30    MalformedControlFlowGraph,
31    MissingSymbol(String),
32    ConstIndexOutOfRange { index: usize, len: usize },
33}
34
35impl Display for InternalError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Self::StackUnderflow => write!(f, "Invalid CFG, stack underflow"),
39            Self::InconsistentStackDepth => write!(f, "Invalid CFG, inconsistent stackdepth"),
40            Self::InvalidStackEffect => write!(f, "Invalid stack effect"),
41            Self::MalformedControlFlowGraph => write!(f, "malformed control flow graph."),
42            Self::MissingSymbol(s) => write!(
43                f,
44                "The symbol '{s}' must be present in the symbol table, even when it is undefined in python."
45            ),
46            Self::ConstIndexOutOfRange { index, len } => {
47                write!(
48                    f,
49                    "LOAD_CONST index {index} is out of range for consts (len={len})"
50                )
51            }
52        }
53    }
54}
55
56#[derive(Debug)]
57#[non_exhaustive]
58pub enum CodegenErrorType {
59    /// Invalid assignment, cannot store value in target.
60    Assign(&'static str),
61    /// Invalid delete
62    Delete(&'static str),
63    SyntaxError(String),
64    /// Multiple `*` detected
65    MultipleStarArgs,
66    MultipleStarredExpressionsInSequencePattern,
67    MultipleStarredNamesInSequencePattern,
68    /// Misplaced `*` expression
69    InvalidStarExpr,
70    /// Break statement outside of loop.
71    InvalidBreak,
72    /// Continue statement outside of loop.
73    InvalidContinue,
74    InvalidReturn,
75    InvalidYield,
76    InvalidYieldFrom,
77    InvalidAwait,
78    InvalidAsyncFor,
79    InvalidAsyncWith,
80    InvalidAsyncComprehension,
81    AsyncYieldFrom,
82    AsyncReturnValue,
83    InvalidFuturePlacement,
84    InvalidFutureFeature(String),
85    InvalidFutureBraces,
86    RecursionError,
87    TooManyStarUnpack,
88    TooManyExpressionsInStarUnpackingSequencePattern,
89    EmptyWithItems,
90    EmptyWithBody,
91    ForbiddenName,
92    DuplicateStore(String),
93    UnreachableWildcardPattern,
94    UnreachableNameCapturePattern(String),
95    RepeatedAttributePattern(String),
96    ConflictingNameBindPattern,
97    /// break/continue/return inside except* block
98    BreakContinueReturnInExceptStar,
99}
100
101impl core::error::Error for CodegenErrorType {}
102
103impl fmt::Display for CodegenErrorType {
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        match self {
106            Self::Assign(target) => write!(f, "cannot assign to {target}"),
107            Self::Delete(target) => write!(f, "cannot delete {target}"),
108            Self::SyntaxError(err) => write!(f, "{}", err.as_str()),
109            Self::MultipleStarArgs => {
110                write!(f, "multiple starred expressions in assignment")
111            }
112            Self::MultipleStarredExpressionsInSequencePattern => {
113                write!(f, "multiple starred expressions in sequence pattern")
114            }
115            Self::MultipleStarredNamesInSequencePattern => {
116                write!(f, "multiple starred names in sequence pattern")
117            }
118            Self::InvalidStarExpr => write!(f, "can't use starred expression here"),
119            Self::InvalidBreak => write!(f, "'break' outside loop"),
120            Self::InvalidContinue => write!(f, "'continue' not properly in loop"),
121            Self::InvalidReturn => write!(f, "'return' outside function"),
122            Self::InvalidYield => write!(f, "'yield' outside function"),
123            Self::InvalidYieldFrom => write!(f, "'yield from' outside function"),
124            Self::InvalidAwait => write!(f, "'await' outside async function"),
125            Self::InvalidAsyncFor => write!(f, "'async for' outside async function"),
126            Self::InvalidAsyncWith => write!(f, "'async with' outside async function"),
127            Self::InvalidAsyncComprehension => {
128                write!(
129                    f,
130                    "asynchronous comprehension outside of an asynchronous function"
131                )
132            }
133            Self::AsyncYieldFrom => write!(f, "'yield from' inside async function"),
134            Self::AsyncReturnValue => write!(f, "'return' with value in async generator"),
135            Self::InvalidFuturePlacement => write!(
136                f,
137                "from __future__ imports must occur at the beginning of the file"
138            ),
139            Self::InvalidFutureFeature(feat) => {
140                write!(f, "future feature {feat} is not defined")
141            }
142            Self::InvalidFutureBraces => write!(f, "not a chance"),
143            Self::RecursionError => {
144                write!(f, "maximum recursion depth exceeded during compilation")
145            }
146            Self::TooManyStarUnpack => {
147                write!(f, "too many expressions in star-unpacking assignment")
148            }
149            Self::TooManyExpressionsInStarUnpackingSequencePattern => {
150                write!(f, "too many expressions in star-unpacking sequence pattern")
151            }
152            Self::EmptyWithItems => {
153                write!(f, "empty items on With")
154            }
155            Self::EmptyWithBody => {
156                write!(f, "empty body on With")
157            }
158            Self::ForbiddenName => {
159                write!(f, "forbidden attribute name")
160            }
161            Self::DuplicateStore(s) => write!(f, "multiple assignments to name '{s}' in pattern"),
162            Self::UnreachableWildcardPattern => {
163                write!(f, "wildcard makes remaining patterns unreachable")
164            }
165            Self::UnreachableNameCapturePattern(name) => {
166                write!(
167                    f,
168                    "name capture '{name}' makes remaining patterns unreachable"
169                )
170            }
171            Self::RepeatedAttributePattern(name) => {
172                write!(f, "attribute name repeated in class pattern: {name}")
173            }
174            Self::ConflictingNameBindPattern => {
175                write!(f, "alternative patterns bind different names")
176            }
177            Self::BreakContinueReturnInExceptStar => {
178                write!(
179                    f,
180                    "'break', 'continue' and 'return' cannot appear in an except* block"
181                )
182            }
183        }
184    }
185}