cairo_lang_semantic/expr/
objects.rs

1use cairo_lang_debug::DebugWithDb;
2use cairo_lang_defs::ids::{MemberId, NamedLanguageElementId, StatementUseId, VarId};
3use cairo_lang_diagnostics::DiagnosticAdded;
4use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
5use cairo_lang_syntax::node::ast;
6use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
7use id_arena::{Arena, Id};
8use num_bigint::BigInt;
9
10use super::fmt::ExprFormatter;
11use super::pattern::Pattern;
12use crate::db::SemanticGroup;
13use crate::items::constant::ConstValueId;
14use crate::{ConcreteStructId, FunctionId, TypeId, semantic};
15
16pub type PatternId = Id<Pattern>;
17pub type ExprId = Id<Expr>;
18pub type StatementId = Id<Statement>;
19
20impl DebugWithDb<ExprFormatter<'_>> for PatternId {
21    fn fmt(
22        &self,
23        f: &mut std::fmt::Formatter<'_>,
24        expr_formatter: &ExprFormatter<'_>,
25    ) -> std::fmt::Result {
26        expr_formatter.db.pattern_semantic(expr_formatter.function_id, *self).fmt(f, expr_formatter)
27    }
28}
29impl DebugWithDb<ExprFormatter<'_>> for ExprId {
30    fn fmt(
31        &self,
32        f: &mut std::fmt::Formatter<'_>,
33        expr_formatter: &ExprFormatter<'_>,
34    ) -> std::fmt::Result {
35        expr_formatter.db.expr_semantic(expr_formatter.function_id, *self).fmt(f, expr_formatter)
36    }
37}
38impl DebugWithDb<ExprFormatter<'_>> for StatementId {
39    fn fmt(
40        &self,
41        f: &mut std::fmt::Formatter<'_>,
42        expr_formatter: &ExprFormatter<'_>,
43    ) -> std::fmt::Result {
44        expr_formatter
45            .db
46            .statement_semantic(expr_formatter.function_id, *self)
47            .fmt(f, expr_formatter)
48    }
49}
50
51#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
52#[debug_db(ExprFormatter<'a>)]
53pub enum Statement {
54    Expr(StatementExpr),
55    Let(StatementLet),
56    Continue(StatementContinue),
57    Return(StatementReturn),
58    Break(StatementBreak),
59    Item(StatementItem),
60}
61impl Statement {
62    pub fn stable_ptr(&self) -> ast::StatementPtr {
63        match self {
64            Statement::Expr(stmt) => stmt.stable_ptr,
65            Statement::Let(stmt) => stmt.stable_ptr,
66            Statement::Continue(stmt) => stmt.stable_ptr,
67            Statement::Return(stmt) => stmt.stable_ptr,
68            Statement::Break(stmt) => stmt.stable_ptr,
69            Statement::Item(stmt) => stmt.stable_ptr,
70        }
71    }
72}
73
74impl From<&Statement> for SyntaxStablePtrId {
75    fn from(statement: &Statement) -> Self {
76        statement.stable_ptr().into()
77    }
78}
79
80#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
81#[debug_db(ExprFormatter<'a>)]
82pub struct StatementExpr {
83    pub expr: ExprId,
84    #[hide_field_debug_with_db]
85    #[dont_rewrite]
86    pub stable_ptr: ast::StatementPtr,
87}
88
89#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
90#[debug_db(ExprFormatter<'a>)]
91pub struct StatementLet {
92    pub pattern: PatternId,
93    pub expr: ExprId,
94    #[hide_field_debug_with_db]
95    #[dont_rewrite]
96    pub stable_ptr: ast::StatementPtr,
97}
98
99#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
100#[debug_db(ExprFormatter<'a>)]
101pub struct StatementContinue {
102    #[hide_field_debug_with_db]
103    #[dont_rewrite]
104    pub stable_ptr: ast::StatementPtr,
105}
106
107#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
108#[debug_db(ExprFormatter<'a>)]
109pub struct StatementReturn {
110    pub expr_option: Option<ExprId>,
111    #[hide_field_debug_with_db]
112    #[dont_rewrite]
113    pub stable_ptr: ast::StatementPtr,
114}
115
116#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
117#[debug_db(ExprFormatter<'a>)]
118pub struct StatementBreak {
119    pub expr_option: Option<ExprId>,
120    #[hide_field_debug_with_db]
121    #[dont_rewrite]
122    pub stable_ptr: ast::StatementPtr,
123}
124
125#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
126#[debug_db(ExprFormatter<'a>)]
127pub struct StatementItem {
128    #[hide_field_debug_with_db]
129    #[dont_rewrite]
130    pub stable_ptr: ast::StatementPtr,
131}
132
133// Expressions.
134#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
135#[debug_db(ExprFormatter<'a>)]
136pub enum Expr {
137    Tuple(ExprTuple),
138    Snapshot(ExprSnapshot),
139    Desnap(ExprDesnap),
140    Assignment(ExprAssignment),
141    LogicalOperator(ExprLogicalOperator),
142    Block(ExprBlock),
143    Loop(ExprLoop),
144    While(ExprWhile),
145    For(ExprFor),
146    FunctionCall(ExprFunctionCall),
147    Match(ExprMatch),
148    If(ExprIf),
149    Var(ExprVar),
150    Literal(ExprLiteral),
151    StringLiteral(ExprStringLiteral),
152    MemberAccess(ExprMemberAccess),
153    StructCtor(ExprStructCtor),
154    EnumVariantCtor(ExprEnumVariantCtor),
155    PropagateError(ExprPropagateError),
156    Constant(ExprConstant),
157    FixedSizeArray(ExprFixedSizeArray),
158    ExprClosure(ExprClosure),
159    Missing(ExprMissing),
160}
161impl Expr {
162    pub fn ty(&self) -> semantic::TypeId {
163        match self {
164            Expr::Assignment(expr) => expr.ty,
165            Expr::Tuple(expr) => expr.ty,
166            Expr::Snapshot(expr) => expr.ty,
167            Expr::Desnap(expr) => expr.ty,
168            Expr::LogicalOperator(expr) => expr.ty,
169            Expr::Block(expr) => expr.ty,
170            Expr::Loop(expr) => expr.ty,
171            Expr::While(expr) => expr.ty,
172            Expr::For(expr) => expr.ty,
173            Expr::FunctionCall(expr) => expr.ty,
174            Expr::Match(expr) => expr.ty,
175            Expr::If(expr) => expr.ty,
176            Expr::Var(expr) => expr.ty,
177            Expr::Literal(expr) => expr.ty,
178            Expr::StringLiteral(expr) => expr.ty,
179            Expr::MemberAccess(expr) => expr.ty,
180            Expr::StructCtor(expr) => expr.ty,
181            Expr::EnumVariantCtor(expr) => expr.ty,
182            Expr::PropagateError(expr) => expr.ok_variant.ty,
183            Expr::Constant(expr) => expr.ty,
184            Expr::Missing(expr) => expr.ty,
185            Expr::FixedSizeArray(expr) => expr.ty,
186            Expr::ExprClosure(expr) => expr.ty,
187        }
188    }
189    pub fn stable_ptr(&self) -> ast::ExprPtr {
190        match self {
191            Expr::Assignment(expr) => expr.stable_ptr,
192            Expr::Tuple(expr) => expr.stable_ptr,
193            Expr::Snapshot(expr) => expr.stable_ptr,
194            Expr::Desnap(expr) => expr.stable_ptr,
195            Expr::LogicalOperator(expr) => expr.stable_ptr,
196            Expr::Block(expr) => expr.stable_ptr,
197            Expr::Loop(expr) => expr.stable_ptr,
198            Expr::While(expr) => expr.stable_ptr,
199            Expr::For(expr) => expr.stable_ptr,
200            Expr::FunctionCall(expr) => expr.stable_ptr,
201            Expr::Match(expr) => expr.stable_ptr,
202            Expr::If(expr) => expr.stable_ptr,
203            Expr::Var(expr) => expr.stable_ptr,
204            Expr::Literal(expr) => expr.stable_ptr,
205            Expr::StringLiteral(expr) => expr.stable_ptr,
206            Expr::MemberAccess(expr) => expr.stable_ptr,
207            Expr::StructCtor(expr) => expr.stable_ptr,
208            Expr::EnumVariantCtor(expr) => expr.stable_ptr,
209            Expr::PropagateError(expr) => expr.stable_ptr,
210            Expr::Constant(expr) => expr.stable_ptr,
211            Expr::Missing(expr) => expr.stable_ptr,
212            Expr::FixedSizeArray(expr) => expr.stable_ptr,
213            Expr::ExprClosure(expr) => expr.stable_ptr,
214        }
215    }
216
217    pub fn as_member_path(&self) -> Option<ExprVarMemberPath> {
218        match self {
219            Expr::Var(expr) => Some(ExprVarMemberPath::Var(expr.clone())),
220            Expr::MemberAccess(expr) => expr.member_path.clone(),
221            _ => None,
222        }
223    }
224}
225
226impl From<&Expr> for SyntaxStablePtrId {
227    fn from(expr: &Expr) -> Self {
228        expr.stable_ptr().into()
229    }
230}
231
232#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
233#[debug_db(ExprFormatter<'a>)]
234pub struct ExprTuple {
235    pub items: Vec<ExprId>,
236    pub ty: semantic::TypeId,
237    #[hide_field_debug_with_db]
238    #[dont_rewrite]
239    pub stable_ptr: ast::ExprPtr,
240}
241
242#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
243#[debug_db(ExprFormatter<'a>)]
244pub struct ExprFixedSizeArray {
245    pub items: FixedSizeArrayItems,
246    pub ty: semantic::TypeId,
247    #[hide_field_debug_with_db]
248    #[dont_rewrite]
249    pub stable_ptr: ast::ExprPtr,
250}
251
252/// Either a vector of items, if all was written in the code i.e. ([10, 11, 12] or [10, 10, 10]), or
253/// a value and a size, if the array was written as ([10; 3]).
254#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
255#[debug_db(ExprFormatter<'a>)]
256pub enum FixedSizeArrayItems {
257    Items(Vec<ExprId>),
258    ValueAndSize(ExprId, ConstValueId),
259}
260
261#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
262#[debug_db(ExprFormatter<'a>)]
263pub struct ExprSnapshot {
264    pub inner: ExprId,
265    pub ty: semantic::TypeId,
266    #[hide_field_debug_with_db]
267    #[dont_rewrite]
268    pub stable_ptr: ast::ExprPtr,
269}
270
271#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
272#[debug_db(ExprFormatter<'a>)]
273pub struct ExprDesnap {
274    pub inner: ExprId,
275    pub ty: semantic::TypeId,
276    #[hide_field_debug_with_db]
277    #[dont_rewrite]
278    pub stable_ptr: ast::ExprPtr,
279}
280
281#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
282#[debug_db(ExprFormatter<'a>)]
283pub struct ExprBlock {
284    pub statements: Vec<StatementId>,
285    /// Blocks may end with an expression, without a trailing `;`.
286    /// In this case, `tail` will be Some(expr) with that expression.
287    /// The block expression will evaluate to this tail expression.
288    /// Otherwise, this will be None.
289    pub tail: Option<ExprId>,
290    pub ty: semantic::TypeId,
291    #[hide_field_debug_with_db]
292    #[dont_rewrite]
293    pub stable_ptr: ast::ExprPtr,
294}
295
296#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
297#[debug_db(ExprFormatter<'a>)]
298pub struct ExprLoop {
299    pub body: ExprId,
300    pub ty: semantic::TypeId,
301    #[hide_field_debug_with_db]
302    #[dont_rewrite]
303    pub stable_ptr: ast::ExprPtr,
304}
305
306#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
307#[debug_db(ExprFormatter<'a>)]
308pub struct ExprWhile {
309    pub condition: Condition,
310    pub body: ExprId,
311    pub ty: semantic::TypeId,
312    #[hide_field_debug_with_db]
313    #[dont_rewrite]
314    pub stable_ptr: ast::ExprPtr,
315}
316
317#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
318#[debug_db(ExprFormatter<'a>)]
319pub struct ExprFor {
320    pub into_iter: FunctionId,
321    pub into_iter_member_path: ExprVarMemberPath,
322    pub next_function_id: FunctionId,
323    pub expr_id: ExprId,
324    pub pattern: PatternId,
325    pub body: ExprId,
326    pub ty: semantic::TypeId,
327    #[hide_field_debug_with_db]
328    #[dont_rewrite]
329    pub stable_ptr: ast::ExprPtr,
330}
331
332/// A sequence of member accesses of a variable. For example: a, a.b, a.b.c, ...
333#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
334pub enum ExprVarMemberPath {
335    Var(ExprVar),
336    Member {
337        parent: Box<ExprVarMemberPath>,
338        member_id: MemberId,
339        #[dont_rewrite]
340        stable_ptr: ast::ExprPtr,
341        concrete_struct_id: ConcreteStructId,
342        // Type of the member.
343        ty: TypeId,
344    },
345}
346impl ExprVarMemberPath {
347    pub fn base_var(&self) -> VarId {
348        match self {
349            ExprVarMemberPath::Var(expr) => expr.var,
350            ExprVarMemberPath::Member { parent, .. } => parent.base_var(),
351        }
352    }
353    pub fn ty(&self) -> TypeId {
354        match self {
355            ExprVarMemberPath::Var(expr) => expr.ty,
356            ExprVarMemberPath::Member { ty, .. } => *ty,
357        }
358    }
359    pub fn stable_ptr(&self) -> ast::ExprPtr {
360        match self {
361            ExprVarMemberPath::Var(var) => var.stable_ptr,
362            ExprVarMemberPath::Member { stable_ptr, .. } => *stable_ptr,
363        }
364    }
365}
366impl<'a> DebugWithDb<ExprFormatter<'a>> for ExprVarMemberPath {
367    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &ExprFormatter<'a>) -> std::fmt::Result {
368        match self {
369            ExprVarMemberPath::Var(var) => var.fmt(f, db),
370            ExprVarMemberPath::Member { parent, member_id, .. } => {
371                write!(f, "{:?}::{}", parent.debug(db), member_id.name(db.db.upcast()))
372            }
373        }
374    }
375}
376#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
377#[debug_db(ExprFormatter<'a>)]
378pub struct ExprClosure {
379    pub body: ExprId,
380    pub params: Vec<semantic::Parameter>,
381    #[hide_field_debug_with_db]
382    #[dont_rewrite]
383    pub stable_ptr: ast::ExprPtr,
384    pub ty: TypeId,
385}
386
387#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
388#[debug_db(ExprFormatter<'a>)]
389pub enum ExprFunctionCallArg {
390    Reference(ExprVarMemberPath),
391    Value(ExprId),
392}
393
394#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
395#[debug_db(ExprFormatter<'a>)]
396pub struct ExprFunctionCall {
397    pub function: FunctionId,
398    pub args: Vec<ExprFunctionCallArg>,
399    /// The `__coupon__` argument of the function call, if used. Attaching a coupon to a function
400    /// means that the coupon is used instead of reducing the cost of the called function from the
401    /// gas wallet. In particular, the cost of such a call is constant.
402    pub coupon_arg: Option<ExprId>,
403    pub ty: semantic::TypeId,
404    #[hide_field_debug_with_db]
405    #[dont_rewrite]
406    pub stable_ptr: ast::ExprPtr,
407}
408
409#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
410#[debug_db(ExprFormatter<'a>)]
411pub struct ExprMatch {
412    pub matched_expr: ExprId,
413    pub arms: Vec<MatchArm>,
414    pub ty: semantic::TypeId,
415    #[hide_field_debug_with_db]
416    #[dont_rewrite]
417    pub stable_ptr: ast::ExprPtr,
418}
419
420#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
421#[debug_db(ExprFormatter<'a>)]
422pub struct ExprIf {
423    pub condition: Condition,
424    pub if_block: ExprId,
425    pub else_block: Option<ExprId>,
426    pub ty: semantic::TypeId,
427    #[hide_field_debug_with_db]
428    #[dont_rewrite]
429    pub stable_ptr: ast::ExprPtr,
430}
431
432#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
433#[debug_db(ExprFormatter<'a>)]
434pub enum Condition {
435    BoolExpr(ExprId),
436    Let(ExprId, Vec<PatternId>),
437}
438
439#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
440#[debug_db(ExprFormatter<'a>)]
441pub struct MatchArm {
442    pub patterns: Vec<PatternId>,
443    pub expression: ExprId,
444}
445
446#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
447#[debug_db(ExprFormatter<'a>)]
448pub struct ExprAssignment {
449    pub ref_arg: ExprVarMemberPath,
450    pub rhs: semantic::ExprId,
451    // ExprAssignment is always of unit type.
452    pub ty: semantic::TypeId,
453    #[hide_field_debug_with_db]
454    #[dont_rewrite]
455    pub stable_ptr: ast::ExprPtr,
456}
457
458#[derive(Clone, Debug, Eq, Hash, PartialEq)]
459pub enum LogicalOperator {
460    AndAnd,
461    OrOr,
462}
463
464#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
465#[debug_db(ExprFormatter<'a>)]
466pub struct ExprLogicalOperator {
467    pub lhs: semantic::ExprId,
468    #[dont_rewrite]
469    pub op: LogicalOperator,
470    pub rhs: semantic::ExprId,
471    // ExprLogicalOperator is always of bool type.
472    pub ty: semantic::TypeId,
473    #[hide_field_debug_with_db]
474    #[dont_rewrite]
475    pub stable_ptr: ast::ExprPtr,
476}
477
478#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
479pub struct ExprVar {
480    pub var: VarId,
481    pub ty: semantic::TypeId,
482    #[dont_rewrite]
483    pub stable_ptr: ast::ExprPtr,
484}
485impl<'a> DebugWithDb<ExprFormatter<'a>> for ExprVar {
486    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &ExprFormatter<'a>) -> std::fmt::Result {
487        self.var.fmt(f, db)
488    }
489}
490
491// TODO(yuval): rename to ExprNumericLiteral.
492#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
493#[debug_db(ExprFormatter<'a>)]
494pub struct ExprLiteral {
495    #[dont_rewrite]
496    pub value: BigInt,
497    pub ty: semantic::TypeId,
498    #[hide_field_debug_with_db]
499    #[dont_rewrite]
500    pub stable_ptr: ast::ExprPtr,
501}
502
503#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
504#[debug_db(ExprFormatter<'a>)]
505pub struct ExprStringLiteral {
506    #[dont_rewrite]
507    pub value: String,
508    pub ty: semantic::TypeId,
509    #[hide_field_debug_with_db]
510    #[dont_rewrite]
511    pub stable_ptr: ast::ExprPtr,
512}
513
514#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
515#[debug_db(ExprFormatter<'a>)]
516pub struct ExprMemberAccess {
517    pub expr: semantic::ExprId,
518    pub concrete_struct_id: ConcreteStructId,
519    pub member: MemberId,
520    pub ty: semantic::TypeId,
521    #[hide_field_debug_with_db]
522    pub member_path: Option<ExprVarMemberPath>,
523    #[hide_field_debug_with_db]
524    #[dont_rewrite]
525    pub n_snapshots: usize,
526    #[hide_field_debug_with_db]
527    #[dont_rewrite]
528    pub stable_ptr: ast::ExprPtr,
529}
530
531#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
532#[debug_db(ExprFormatter<'a>)]
533pub struct ExprStructCtor {
534    pub concrete_struct_id: ConcreteStructId,
535    pub members: Vec<(MemberId, ExprId)>,
536    /// The base struct to copy missing members from if provided.
537    /// For example `let x = MyStruct { a: 1, ..base }`.
538    pub base_struct: Option<ExprId>,
539    pub ty: semantic::TypeId,
540    #[hide_field_debug_with_db]
541    #[dont_rewrite]
542    pub stable_ptr: ast::ExprPtr,
543}
544
545#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
546#[debug_db(ExprFormatter<'a>)]
547pub struct ExprEnumVariantCtor {
548    pub variant: semantic::ConcreteVariant,
549    pub value_expr: ExprId,
550    pub ty: semantic::TypeId,
551    #[hide_field_debug_with_db]
552    #[dont_rewrite]
553    pub stable_ptr: ast::ExprPtr,
554}
555
556#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
557#[debug_db(ExprFormatter<'a>)]
558pub struct ExprPropagateError {
559    pub inner: ExprId,
560    pub ok_variant: semantic::ConcreteVariant,
561    pub err_variant: semantic::ConcreteVariant,
562    pub func_err_variant: semantic::ConcreteVariant,
563    #[hide_field_debug_with_db]
564    #[dont_rewrite]
565    pub stable_ptr: ast::ExprPtr,
566}
567
568#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
569#[debug_db(ExprFormatter<'a>)]
570pub struct ExprConstant {
571    pub const_value_id: ConstValueId,
572    pub ty: semantic::TypeId,
573    #[dont_rewrite]
574    #[hide_field_debug_with_db]
575    pub stable_ptr: ast::ExprPtr,
576}
577
578#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
579#[debug_db(ExprFormatter<'a>)]
580pub struct ExprUse {
581    pub const_value_id: StatementUseId,
582    pub ty: semantic::TypeId,
583    #[dont_rewrite]
584    #[hide_field_debug_with_db]
585    pub stable_ptr: ast::ExprPtr,
586}
587
588#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
589#[debug_db(ExprFormatter<'a>)]
590pub struct ExprMissing {
591    pub ty: semantic::TypeId,
592    #[hide_field_debug_with_db]
593    #[dont_rewrite]
594    pub stable_ptr: ast::ExprPtr,
595    #[hide_field_debug_with_db]
596    #[dont_rewrite]
597    pub diag_added: DiagnosticAdded,
598}
599
600/// Arena for semantic expressions, patterns, and statements.
601#[derive(Clone, Debug, Default, PartialEq, Eq, DebugWithDb)]
602#[debug_db(dyn SemanticGroup + 'static)]
603pub struct Arenas {
604    pub exprs: Arena<semantic::Expr>,
605    pub patterns: Arena<semantic::Pattern>,
606    pub statements: Arena<semantic::Statement>,
607}