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