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 cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
8use id_arena::{Arena, ArenaBehavior};
9use num_bigint::BigInt;
10use salsa::Database;
11
12use super::fmt::ExprFormatter;
13use crate::items::constant::ConstValueId;
14use crate::{ConcreteStructId, FunctionId, TypeId, semantic};
15
16macro_rules! define_arena_id {
18 ($id:ident, $behaviour:ident) => {
19 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
20 pub struct $id(u32, usize);
21
22 impl core::fmt::Debug for $id {
23 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24 f.debug_tuple(stringify!($id)).field(&self.1).finish()
25 }
26 }
27
28 #[derive(Clone, Debug, PartialEq, Eq)]
29 pub struct $behaviour;
30 impl ArenaBehavior for $behaviour {
31 type Id = $id;
32
33 fn new_id(arena_id: u32, index: usize) -> Self::Id {
34 $id(arena_id, index)
35 }
36
37 fn arena_id(id: Self::Id) -> u32 {
38 id.0
39 }
40
41 fn index(id: Self::Id) -> usize {
42 id.1
43 }
44 }
45 };
46}
47
48define_arena_id!(PatternId, PatternArenaBehavior);
49pub type PatternArena<'db> = Arena<semantic::Pattern<'db>, PatternArenaBehavior>;
50define_arena_id!(ExprId, ExprArenaBehavior);
51pub type ExprArena<'db> = Arena<semantic::Expr<'db>, ExprArenaBehavior>;
52define_arena_id!(StatementId, StatementArenaBehavior);
53pub type StatementArena<'db> = Arena<semantic::Statement<'db>, StatementArenaBehavior>;
54
55#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
56#[debug_db(ExprFormatter<'db>)]
57pub enum Statement<'db> {
58 Expr(StatementExpr<'db>),
59 Let(StatementLet<'db>),
60 Continue(StatementContinue<'db>),
61 Return(StatementReturn<'db>),
62 Break(StatementBreak<'db>),
63 Item(StatementItem<'db>),
64}
65impl<'db> Statement<'db> {
66 pub fn stable_ptr(&self) -> ast::StatementPtr<'db> {
67 match self {
68 Statement::Expr(stmt) => stmt.stable_ptr,
69 Statement::Let(stmt) => stmt.stable_ptr,
70 Statement::Continue(stmt) => stmt.stable_ptr,
71 Statement::Return(stmt) => stmt.stable_ptr,
72 Statement::Break(stmt) => stmt.stable_ptr,
73 Statement::Item(stmt) => stmt.stable_ptr,
74 }
75 }
76}
77
78impl<'db> From<&Statement<'db>> for SyntaxStablePtrId<'db> {
79 fn from(statement: &Statement<'db>) -> Self {
80 statement.stable_ptr().into()
81 }
82}
83
84#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
85#[debug_db(ExprFormatter<'db>)]
86pub struct StatementExpr<'db> {
87 pub expr: ExprId,
88 #[hide_field_debug_with_db]
89 #[dont_rewrite]
90 pub stable_ptr: ast::StatementPtr<'db>,
91}
92
93#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
94#[debug_db(ExprFormatter<'db>)]
95pub struct StatementLet<'db> {
96 pub pattern: PatternId,
97 pub expr: ExprId,
98 pub else_clause: Option<ExprId>,
99 #[hide_field_debug_with_db]
100 #[dont_rewrite]
101 pub stable_ptr: ast::StatementPtr<'db>,
102}
103
104#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
105#[debug_db(ExprFormatter<'db>)]
106pub struct StatementContinue<'db> {
107 #[hide_field_debug_with_db]
108 #[dont_rewrite]
109 pub stable_ptr: ast::StatementPtr<'db>,
110}
111
112#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
113#[debug_db(ExprFormatter<'db>)]
114pub struct StatementReturn<'db> {
115 pub expr_option: Option<ExprId>,
116 #[hide_field_debug_with_db]
117 #[dont_rewrite]
118 pub stable_ptr: ast::StatementPtr<'db>,
119}
120
121#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
122#[debug_db(ExprFormatter<'db>)]
123pub struct StatementBreak<'db> {
124 pub expr_option: Option<ExprId>,
125 #[hide_field_debug_with_db]
126 #[dont_rewrite]
127 pub stable_ptr: ast::StatementPtr<'db>,
128}
129
130#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
131#[debug_db(ExprFormatter<'db>)]
132pub struct StatementItem<'db> {
133 #[hide_field_debug_with_db]
134 #[dont_rewrite]
135 pub stable_ptr: ast::StatementPtr<'db>,
136}
137
138#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
140#[debug_db(ExprFormatter<'db>)]
141pub enum Expr<'db> {
142 Tuple(ExprTuple<'db>),
143 Snapshot(ExprSnapshot<'db>),
144 Desnap(ExprDesnap<'db>),
145 Assignment(ExprAssignment<'db>),
146 LogicalOperator(ExprLogicalOperator<'db>),
147 Block(ExprBlock<'db>),
148 Loop(ExprLoop<'db>),
149 While(ExprWhile<'db>),
150 For(ExprFor<'db>),
151 FunctionCall(ExprFunctionCall<'db>),
152 Match(ExprMatch<'db>),
153 If(ExprIf<'db>),
154 Var(ExprVar<'db>),
155 Literal(ExprLiteral<'db>),
156 StringLiteral(ExprStringLiteral<'db>),
157 MemberAccess(ExprMemberAccess<'db>),
158 StructCtor(ExprStructCtor<'db>),
159 EnumVariantCtor(ExprEnumVariantCtor<'db>),
160 PropagateError(ExprPropagateError<'db>),
161 Constant(ExprConstant<'db>),
162 FixedSizeArray(ExprFixedSizeArray<'db>),
163 ExprClosure(ExprClosure<'db>),
164 Missing(ExprMissing<'db>),
165}
166impl<'db> Expr<'db> {
167 pub fn ty(&self) -> semantic::TypeId<'db> {
168 match self {
169 Expr::Assignment(expr) => expr.ty,
170 Expr::Tuple(expr) => expr.ty,
171 Expr::Snapshot(expr) => expr.ty,
172 Expr::Desnap(expr) => expr.ty,
173 Expr::LogicalOperator(expr) => expr.ty,
174 Expr::Block(expr) => expr.ty,
175 Expr::Loop(expr) => expr.ty,
176 Expr::While(expr) => expr.ty,
177 Expr::For(expr) => expr.ty,
178 Expr::FunctionCall(expr) => expr.ty,
179 Expr::Match(expr) => expr.ty,
180 Expr::If(expr) => expr.ty,
181 Expr::Var(expr) => expr.ty,
182 Expr::Literal(expr) => expr.ty,
183 Expr::StringLiteral(expr) => expr.ty,
184 Expr::MemberAccess(expr) => expr.ty,
185 Expr::StructCtor(expr) => expr.ty,
186 Expr::EnumVariantCtor(expr) => expr.ty,
187 Expr::PropagateError(expr) => expr.ok_variant.ty,
188 Expr::Constant(expr) => expr.ty,
189 Expr::Missing(expr) => expr.ty,
190 Expr::FixedSizeArray(expr) => expr.ty,
191 Expr::ExprClosure(expr) => expr.ty,
192 }
193 }
194 pub fn stable_ptr(&self) -> ast::ExprPtr<'db> {
195 match self {
196 Expr::Assignment(expr) => expr.stable_ptr,
197 Expr::Tuple(expr) => expr.stable_ptr,
198 Expr::Snapshot(expr) => expr.stable_ptr,
199 Expr::Desnap(expr) => expr.stable_ptr,
200 Expr::LogicalOperator(expr) => expr.stable_ptr,
201 Expr::Block(expr) => expr.stable_ptr,
202 Expr::Loop(expr) => expr.stable_ptr,
203 Expr::While(expr) => expr.stable_ptr,
204 Expr::For(expr) => expr.stable_ptr,
205 Expr::FunctionCall(expr) => expr.stable_ptr,
206 Expr::Match(expr) => expr.stable_ptr,
207 Expr::If(expr) => expr.stable_ptr,
208 Expr::Var(expr) => expr.stable_ptr,
209 Expr::Literal(expr) => expr.stable_ptr,
210 Expr::StringLiteral(expr) => expr.stable_ptr,
211 Expr::MemberAccess(expr) => expr.stable_ptr,
212 Expr::StructCtor(expr) => expr.stable_ptr,
213 Expr::EnumVariantCtor(expr) => expr.stable_ptr,
214 Expr::PropagateError(expr) => expr.stable_ptr,
215 Expr::Constant(expr) => expr.stable_ptr,
216 Expr::Missing(expr) => expr.stable_ptr,
217 Expr::FixedSizeArray(expr) => expr.stable_ptr,
218 Expr::ExprClosure(expr) => expr.stable_ptr,
219 }
220 }
221
222 pub fn as_member_path(&self) -> Option<ExprVarMemberPath<'db>> {
224 match self {
225 Expr::Var(expr) => Some(ExprVarMemberPath::Var(expr.clone())),
226 Expr::MemberAccess(expr) => expr.member_path.clone(),
227 _ => None,
228 }
229 }
230
231 pub fn is_mutable_var(
233 &self,
234 semantic_defs: &UnorderedHashMap<semantic::VarId<'db>, semantic::Binding<'db>>,
235 ) -> bool {
236 if let Some(base_var) = self.as_member_path().map(|path| path.base_var())
237 && let Some(var_def) = semantic_defs.get(&base_var)
238 {
239 var_def.is_mut()
240 } else {
241 false
242 }
243 }
244}
245
246impl<'db> From<&Expr<'db>> for SyntaxStablePtrId<'db> {
247 fn from(expr: &Expr<'db>) -> Self {
248 expr.stable_ptr().into()
249 }
250}
251
252#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
253#[debug_db(ExprFormatter<'db>)]
254pub struct ExprTuple<'db> {
255 pub items: Vec<ExprId>,
256 pub ty: semantic::TypeId<'db>,
257 #[hide_field_debug_with_db]
258 #[dont_rewrite]
259 pub stable_ptr: ast::ExprPtr<'db>,
260}
261
262#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
263#[debug_db(ExprFormatter<'db>)]
264pub struct ExprFixedSizeArray<'db> {
265 pub items: FixedSizeArrayItems<'db>,
266 pub ty: semantic::TypeId<'db>,
267 #[hide_field_debug_with_db]
268 #[dont_rewrite]
269 pub stable_ptr: ast::ExprPtr<'db>,
270}
271
272#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
275#[debug_db(ExprFormatter<'db>)]
276pub enum FixedSizeArrayItems<'db> {
277 Items(Vec<ExprId>),
278 ValueAndSize(ExprId, ConstValueId<'db>),
279}
280
281#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
282#[debug_db(ExprFormatter<'db>)]
283pub struct ExprSnapshot<'db> {
284 pub inner: ExprId,
285 pub ty: semantic::TypeId<'db>,
286 #[hide_field_debug_with_db]
287 #[dont_rewrite]
288 pub stable_ptr: ast::ExprPtr<'db>,
289}
290
291#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
292#[debug_db(ExprFormatter<'db>)]
293pub struct ExprDesnap<'db> {
294 pub inner: ExprId,
295 pub ty: semantic::TypeId<'db>,
296 #[hide_field_debug_with_db]
297 #[dont_rewrite]
298 pub stable_ptr: ast::ExprPtr<'db>,
299}
300
301#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
302#[debug_db(ExprFormatter<'db>)]
303pub struct ExprBlock<'db> {
304 pub statements: Vec<StatementId>,
305 pub tail: Option<ExprId>,
310 pub ty: semantic::TypeId<'db>,
311 #[hide_field_debug_with_db]
312 #[dont_rewrite]
313 pub stable_ptr: ast::ExprPtr<'db>,
314}
315
316#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
317#[debug_db(ExprFormatter<'db>)]
318pub struct ExprLoop<'db> {
319 pub body: ExprId,
320 pub ty: semantic::TypeId<'db>,
321 #[hide_field_debug_with_db]
322 #[dont_rewrite]
323 pub stable_ptr: ast::ExprPtr<'db>,
324}
325
326#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
327#[debug_db(ExprFormatter<'db>)]
328pub struct ExprWhile<'db> {
329 pub condition: Condition,
330 pub body: ExprId,
331 pub ty: semantic::TypeId<'db>,
332 #[hide_field_debug_with_db]
333 #[dont_rewrite]
334 pub stable_ptr: ast::ExprPtr<'db>,
335}
336
337#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
338#[debug_db(ExprFormatter<'db>)]
339pub struct ExprFor<'db> {
340 pub into_iter: FunctionId<'db>,
341 pub into_iter_member_path: ExprVarMemberPath<'db>,
342 pub next_function_id: FunctionId<'db>,
343 pub expr_id: ExprId,
344 pub pattern: PatternId,
345 pub body: ExprId,
346 pub ty: semantic::TypeId<'db>,
347 #[hide_field_debug_with_db]
348 #[dont_rewrite]
349 pub stable_ptr: ast::ExprPtr<'db>,
350}
351
352#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update)]
354pub enum ExprVarMemberPath<'db> {
355 Var(ExprVar<'db>),
356 Member {
357 parent: Box<ExprVarMemberPath<'db>>,
358 member_id: MemberId<'db>,
359 #[dont_rewrite]
360 stable_ptr: ast::ExprPtr<'db>,
361 concrete_struct_id: ConcreteStructId<'db>,
362 ty: TypeId<'db>,
364 },
365}
366impl<'db> ExprVarMemberPath<'db> {
367 pub fn base_var(&self) -> VarId<'db> {
368 match self {
369 ExprVarMemberPath::Var(expr) => expr.var,
370 ExprVarMemberPath::Member { parent, .. } => parent.base_var(),
371 }
372 }
373 pub fn ty(&self) -> TypeId<'db> {
374 match self {
375 ExprVarMemberPath::Var(expr) => expr.ty,
376 ExprVarMemberPath::Member { ty, .. } => *ty,
377 }
378 }
379 pub fn stable_ptr(&self) -> ast::ExprPtr<'db> {
380 match self {
381 ExprVarMemberPath::Var(var) => var.stable_ptr,
382 ExprVarMemberPath::Member { stable_ptr, .. } => *stable_ptr,
383 }
384 }
385}
386impl<'db> DebugWithDb<'db> for ExprVarMemberPath<'db> {
387 type Db = dyn Database;
388
389 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
390 match self {
391 ExprVarMemberPath::Var(var) => var.fmt(f, db),
392 ExprVarMemberPath::Member { parent, member_id, .. } => {
393 write!(f, "{:?}::{}", parent.debug(db), member_id.name(db).long(db))
394 }
395 }
396 }
397}
398#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
399#[debug_db(ExprFormatter<'db>)]
400pub struct ExprClosure<'db> {
401 pub body: ExprId,
402 pub params: Vec<semantic::Parameter<'db>>,
403 #[hide_field_debug_with_db]
404 #[dont_rewrite]
405 pub stable_ptr: ast::ExprPtr<'db>,
406 pub ty: TypeId<'db>,
407}
408
409#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
410#[debug_db(ExprFormatter<'db>)]
411pub enum ExprFunctionCallArg<'db> {
412 Reference(ExprVarMemberPath<'db>),
413 Value(ExprId),
414}
415
416#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
417#[debug_db(ExprFormatter<'db>)]
418pub struct ExprFunctionCall<'db> {
419 pub function: FunctionId<'db>,
420 pub args: Vec<ExprFunctionCallArg<'db>>,
421 pub coupon_arg: Option<ExprId>,
425 pub ty: semantic::TypeId<'db>,
426 #[hide_field_debug_with_db]
427 #[dont_rewrite]
428 pub stable_ptr: ast::ExprPtr<'db>,
429}
430
431#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
432#[debug_db(ExprFormatter<'db>)]
433pub struct ExprMatch<'db> {
434 pub matched_expr: ExprId,
435 pub arms: Vec<MatchArm>,
436 pub ty: semantic::TypeId<'db>,
437 #[hide_field_debug_with_db]
438 #[dont_rewrite]
439 pub stable_ptr: ast::ExprPtr<'db>,
440}
441
442#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
443#[debug_db(ExprFormatter<'db>)]
444pub struct ExprIf<'db> {
445 pub conditions: Vec<Condition>,
446 pub if_block: ExprId,
447 pub else_block: Option<ExprId>,
448 pub ty: semantic::TypeId<'db>,
449 #[hide_field_debug_with_db]
450 #[dont_rewrite]
451 pub stable_ptr: ast::ExprPtr<'db>,
452}
453
454#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
455#[debug_db(ExprFormatter<'db>)]
456pub enum Condition {
457 BoolExpr(ExprId),
458 Let(ExprId, Vec<PatternId>),
459}
460
461#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
462#[debug_db(ExprFormatter<'db>)]
463pub struct MatchArm {
464 pub patterns: Vec<PatternId>,
465 pub expression: ExprId,
466}
467
468#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
469#[debug_db(ExprFormatter<'db>)]
470pub struct ExprAssignment<'db> {
471 pub ref_arg: ExprVarMemberPath<'db>,
472 pub rhs: semantic::ExprId,
473 pub ty: semantic::TypeId<'db>,
475 #[hide_field_debug_with_db]
476 #[dont_rewrite]
477 pub stable_ptr: ast::ExprPtr<'db>,
478}
479
480#[derive(Clone, Debug, Eq, Hash, PartialEq)]
481pub enum LogicalOperator {
482 AndAnd,
483 OrOr,
484}
485
486#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
487#[debug_db(ExprFormatter<'db>)]
488pub struct ExprLogicalOperator<'db> {
489 pub lhs: semantic::ExprId,
490 #[dont_rewrite]
491 pub op: LogicalOperator,
492 pub rhs: semantic::ExprId,
493 pub ty: semantic::TypeId<'db>,
495 #[hide_field_debug_with_db]
496 #[dont_rewrite]
497 pub stable_ptr: ast::ExprPtr<'db>,
498}
499
500#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject, salsa::Update)]
501pub struct ExprVar<'db> {
502 pub var: VarId<'db>,
503 pub ty: semantic::TypeId<'db>,
504 #[dont_rewrite]
505 pub stable_ptr: ast::ExprPtr<'db>,
506}
507impl<'db> DebugWithDb<'db> for ExprVar<'db> {
508 type Db = dyn Database;
509
510 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
511 self.var.fmt(f, db)
512 }
513}
514
515#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject, salsa::Update)]
517#[debug_db(ExprFormatter<'db>)]
518pub struct ExprLiteral<'db> {
519 #[dont_rewrite]
520 pub value: BigInt,
521 pub ty: semantic::TypeId<'db>,
522 #[hide_field_debug_with_db]
523 #[dont_rewrite]
524 pub stable_ptr: ast::ExprPtr<'db>,
525}
526
527#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject, salsa::Update)]
528#[debug_db(ExprFormatter<'db>)]
529pub struct ExprStringLiteral<'db> {
530 #[dont_rewrite]
531 pub value: String,
532 pub ty: semantic::TypeId<'db>,
533 #[hide_field_debug_with_db]
534 #[dont_rewrite]
535 pub stable_ptr: ast::ExprPtr<'db>,
536}
537
538#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
539#[debug_db(ExprFormatter<'db>)]
540pub struct ExprMemberAccess<'db> {
541 pub expr: semantic::ExprId,
542 pub concrete_struct_id: ConcreteStructId<'db>,
543 pub member: MemberId<'db>,
544 pub ty: semantic::TypeId<'db>,
545 #[hide_field_debug_with_db]
546 pub member_path: Option<ExprVarMemberPath<'db>>,
547 #[hide_field_debug_with_db]
548 #[dont_rewrite]
549 pub n_snapshots: usize,
550 #[hide_field_debug_with_db]
551 #[dont_rewrite]
552 pub stable_ptr: ast::ExprPtr<'db>,
553}
554
555#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
556#[debug_db(ExprFormatter<'db>)]
557pub struct ExprStructCtor<'db> {
558 pub concrete_struct_id: ConcreteStructId<'db>,
559 pub members: Vec<(ExprId, MemberId<'db>)>,
560 pub base_struct: Option<ExprId>,
563 pub ty: semantic::TypeId<'db>,
564 #[hide_field_debug_with_db]
565 #[dont_rewrite]
566 pub stable_ptr: ast::ExprPtr<'db>,
567}
568
569#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
570#[debug_db(ExprFormatter<'db>)]
571pub struct ExprEnumVariantCtor<'db> {
572 pub variant: semantic::ConcreteVariant<'db>,
573 pub value_expr: ExprId,
574 pub ty: semantic::TypeId<'db>,
575 #[hide_field_debug_with_db]
576 #[dont_rewrite]
577 pub stable_ptr: ast::ExprPtr<'db>,
578}
579
580#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
581#[debug_db(ExprFormatter<'db>)]
582pub struct ExprPropagateError<'db> {
583 pub inner: ExprId,
584 pub ok_variant: semantic::ConcreteVariant<'db>,
585 pub err_variant: semantic::ConcreteVariant<'db>,
586 pub func_err_variant: semantic::ConcreteVariant<'db>,
587 #[hide_field_debug_with_db]
588 #[dont_rewrite]
589 pub stable_ptr: ast::ExprPtr<'db>,
590}
591
592#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
593#[debug_db(ExprFormatter<'db>)]
594pub struct ExprConstant<'db> {
595 pub const_value_id: ConstValueId<'db>,
596 pub ty: semantic::TypeId<'db>,
597 #[dont_rewrite]
598 #[hide_field_debug_with_db]
599 pub stable_ptr: ast::ExprPtr<'db>,
600}
601
602#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
603#[debug_db(ExprFormatter<'db>)]
604pub struct ExprUse<'db> {
605 pub const_value_id: StatementUseId<'db>,
606 pub ty: semantic::TypeId<'db>,
607 #[dont_rewrite]
608 #[hide_field_debug_with_db]
609 pub stable_ptr: ast::ExprPtr<'db>,
610}
611
612#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
613#[debug_db(ExprFormatter<'db>)]
614pub struct ExprMissing<'db> {
615 pub ty: semantic::TypeId<'db>,
616 #[hide_field_debug_with_db]
617 #[dont_rewrite]
618 pub stable_ptr: ast::ExprPtr<'db>,
619 #[hide_field_debug_with_db]
620 #[dont_rewrite]
621 pub diag_added: DiagnosticAdded,
622}
623
624#[derive(Clone, Debug, Default, PartialEq, Eq, DebugWithDb)]
626#[debug_db(dyn Database)]
627pub struct Arenas<'db> {
628 pub exprs: ExprArena<'db>,
629 pub patterns: PatternArena<'db>,
630 pub statements: StatementArena<'db>,
631}
632
633unsafe impl<'db> salsa::Update for Arenas<'db> {
634 unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool {
635 let old_arenas: &mut Arenas<'db> = unsafe { &mut *old_pointer };
636
637 if old_arenas.exprs.next_id() != new_value.exprs.next_id()
639 || old_arenas.patterns.next_id() != new_value.patterns.next_id()
640 || old_arenas.statements.next_id() != new_value.statements.next_id()
641 {
642 *old_arenas = new_value;
643 return true;
644 }
645 false
646 }
647}