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