1pub mod body;
4mod expander;
5pub mod lower;
6pub mod path;
7pub mod pretty;
8pub mod scope;
9#[cfg(test)]
10mod tests;
11
12use std::{
13 ops::{Deref, Index},
14 sync::LazyLock,
15};
16
17use cfg::{CfgExpr, CfgOptions};
18use either::Either;
19use hir_expand::{InFile, MacroCallId, mod_path::ModPath, name::Name};
20use la_arena::{Arena, ArenaMap};
21use rustc_hash::FxHashMap;
22use smallvec::SmallVec;
23use span::{Edition, SyntaxContext};
24use syntax::{AstPtr, SyntaxNodePtr, ast};
25use thin_vec::ThinVec;
26use triomphe::Arc;
27use tt::TextRange;
28
29use crate::{
30 BlockId, SyntheticSyntax,
31 db::DefDatabase,
32 expr_store::path::Path,
33 hir::{
34 Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat,
35 PatId, RecordFieldPat, Statement,
36 },
37 nameres::{DefMap, block_def_map},
38 type_ref::{LifetimeRef, LifetimeRefId, PathId, TypeRef, TypeRefId},
39};
40
41pub use self::body::{Body, BodySourceMap};
42pub use self::lower::{
43 hir_assoc_type_binding_to_ast, hir_generic_arg_to_ast, hir_segment_to_ast_segment,
44};
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48pub struct HygieneId(span::SyntaxContext);
49
50impl HygieneId {
51 pub const ROOT: Self = Self(span::SyntaxContext::root(Edition::Edition2015));
53
54 pub fn new(mut ctx: span::SyntaxContext) -> Self {
55 ctx.remove_root_edition();
57 Self(ctx)
58 }
59
60 pub(crate) fn lookup(self) -> SyntaxContext {
62 self.0
63 }
64
65 pub(crate) fn is_root(self) -> bool {
66 self.0.is_root()
67 }
68}
69
70pub type ExprPtr = AstPtr<ast::Expr>;
71pub type ExprSource = InFile<ExprPtr>;
72
73pub type PatPtr = AstPtr<ast::Pat>;
74pub type PatSource = InFile<PatPtr>;
75
76pub type LabelPtr = AstPtr<ast::Label>;
77pub type LabelSource = InFile<LabelPtr>;
78
79pub type FieldPtr = AstPtr<ast::RecordExprField>;
80pub type FieldSource = InFile<FieldPtr>;
81
82pub type PatFieldPtr = AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>;
83pub type PatFieldSource = InFile<PatFieldPtr>;
84
85pub type ExprOrPatPtr = AstPtr<Either<ast::Expr, ast::Pat>>;
86pub type ExprOrPatSource = InFile<ExprOrPatPtr>;
87
88pub type SelfParamPtr = AstPtr<ast::SelfParam>;
89pub type MacroCallPtr = AstPtr<ast::MacroCall>;
90
91pub type TypePtr = AstPtr<ast::Type>;
92pub type TypeSource = InFile<TypePtr>;
93
94pub type LifetimePtr = AstPtr<ast::Lifetime>;
95pub type LifetimeSource = InFile<LifetimePtr>;
96
97#[derive(Debug, PartialEq, Eq)]
100struct ExpressionOnlyStore {
101 exprs: Arena<Expr>,
102 pats: Arena<Pat>,
103 bindings: Arena<Binding>,
104 labels: Arena<Label>,
105 binding_owners: FxHashMap<BindingId, ExprId>,
108 block_scopes: Box<[BlockId]>,
110
111 ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
116}
117
118#[derive(Debug, PartialEq, Eq)]
119pub struct ExpressionStore {
120 expr_only: Option<Box<ExpressionOnlyStore>>,
121 pub types: Arena<TypeRef>,
122 pub lifetimes: Arena<LifetimeRef>,
123}
124
125#[derive(Debug, Eq, Default)]
126struct ExpressionOnlySourceMap {
127 expr_map: FxHashMap<ExprSource, ExprOrPatId>,
130 expr_map_back: ArenaMap<ExprId, ExprOrPatSource>,
131
132 pat_map: FxHashMap<PatSource, ExprOrPatId>,
133 pat_map_back: ArenaMap<PatId, ExprOrPatSource>,
134
135 label_map: FxHashMap<LabelSource, LabelId>,
136 label_map_back: ArenaMap<LabelId, LabelSource>,
137
138 binding_definitions:
139 ArenaMap<BindingId, SmallVec<[PatId; 2 * size_of::<usize>() / size_of::<PatId>()]>>,
140
141 field_map_back: FxHashMap<ExprId, FieldSource>,
144 pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
145
146 template_map: Option<Box<FormatTemplate>>,
147
148 expansions: FxHashMap<InFile<MacroCallPtr>, MacroCallId>,
149
150 diagnostics: ThinVec<ExpressionStoreDiagnostics>,
156}
157
158impl PartialEq for ExpressionOnlySourceMap {
159 fn eq(&self, other: &Self) -> bool {
160 let Self {
164 expr_map: _,
165 expr_map_back,
166 pat_map: _,
167 pat_map_back,
168 label_map: _,
169 label_map_back,
170 binding_definitions: _,
172 field_map_back: _,
174 pat_field_map_back: _,
176 template_map,
177 expansions,
178 diagnostics,
179 } = self;
180 *expr_map_back == other.expr_map_back
181 && *pat_map_back == other.pat_map_back
182 && *label_map_back == other.label_map_back
183 && *template_map == other.template_map
184 && *expansions == other.expansions
185 && *diagnostics == other.diagnostics
186 }
187}
188
189#[derive(Debug, Eq, Default)]
190pub struct ExpressionStoreSourceMap {
191 expr_only: Option<Box<ExpressionOnlySourceMap>>,
192
193 types_map_back: ArenaMap<TypeRefId, TypeSource>,
194 types_map: FxHashMap<TypeSource, TypeRefId>,
195
196 lifetime_map_back: ArenaMap<LifetimeRefId, LifetimeSource>,
197 #[expect(
198 unused,
199 reason = "this is here for completeness, and maybe we'll need it in the future"
200 )]
201 lifetime_map: FxHashMap<LifetimeSource, LifetimeRefId>,
202}
203
204impl PartialEq for ExpressionStoreSourceMap {
205 fn eq(&self, other: &Self) -> bool {
206 let Self { expr_only, types_map_back, types_map: _, lifetime_map_back, lifetime_map: _ } =
210 self;
211 *expr_only == other.expr_only
212 && *types_map_back == other.types_map_back
213 && *lifetime_map_back == other.lifetime_map_back
214 }
215}
216
217#[derive(Debug, Eq, PartialEq, Default)]
219pub struct ExpressionStoreBuilder {
220 pub exprs: Arena<Expr>,
221 pub pats: Arena<Pat>,
222 pub bindings: Arena<Binding>,
223 pub labels: Arena<Label>,
224 pub lifetimes: Arena<LifetimeRef>,
225 pub binding_owners: FxHashMap<BindingId, ExprId>,
226 pub types: Arena<TypeRef>,
227 block_scopes: Vec<BlockId>,
228 ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
229
230 expr_map: FxHashMap<ExprSource, ExprOrPatId>,
233 expr_map_back: ArenaMap<ExprId, ExprOrPatSource>,
234
235 pat_map: FxHashMap<PatSource, ExprOrPatId>,
236 pat_map_back: ArenaMap<PatId, ExprOrPatSource>,
237
238 label_map: FxHashMap<LabelSource, LabelId>,
239 label_map_back: ArenaMap<LabelId, LabelSource>,
240
241 types_map_back: ArenaMap<TypeRefId, TypeSource>,
242 types_map: FxHashMap<TypeSource, TypeRefId>,
243
244 lifetime_map_back: ArenaMap<LifetimeRefId, LifetimeSource>,
245 lifetime_map: FxHashMap<LifetimeSource, LifetimeRefId>,
246
247 binding_definitions:
248 ArenaMap<BindingId, SmallVec<[PatId; 2 * size_of::<usize>() / size_of::<PatId>()]>>,
249
250 field_map_back: FxHashMap<ExprId, FieldSource>,
253 pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
254
255 template_map: Option<Box<FormatTemplate>>,
256
257 expansions: FxHashMap<InFile<MacroCallPtr>, MacroCallId>,
258
259 pub(crate) diagnostics: Vec<ExpressionStoreDiagnostics>,
265}
266
267#[derive(Default, Debug, Eq, PartialEq)]
268struct FormatTemplate {
269 format_args_to_captures: FxHashMap<ExprId, (HygieneId, Vec<(syntax::TextRange, Name)>)>,
271 asm_to_captures: FxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>,
273 implicit_capture_to_source: FxHashMap<ExprId, InFile<(ExprPtr, TextRange)>>,
279}
280
281#[derive(Debug, Eq, PartialEq)]
282pub enum ExpressionStoreDiagnostics {
283 InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
284 UnresolvedMacroCall { node: InFile<MacroCallPtr>, path: ModPath },
285 UnreachableLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
286 AwaitOutsideOfAsync { node: InFile<AstPtr<ast::AwaitExpr>>, location: String },
287 UndeclaredLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
288}
289
290impl ExpressionStoreBuilder {
291 pub fn finish(self) -> (ExpressionStore, ExpressionStoreSourceMap) {
292 let Self {
293 block_scopes,
294 mut exprs,
295 mut labels,
296 mut pats,
297 mut bindings,
298 mut binding_owners,
299 mut ident_hygiene,
300 mut types,
301 mut lifetimes,
302
303 mut expr_map,
304 mut expr_map_back,
305 mut pat_map,
306 mut pat_map_back,
307 mut label_map,
308 mut label_map_back,
309 mut types_map_back,
310 mut types_map,
311 mut lifetime_map_back,
312 mut lifetime_map,
313 mut binding_definitions,
314 mut field_map_back,
315 mut pat_field_map_back,
316 mut template_map,
317 mut expansions,
318 diagnostics,
319 } = self;
320 exprs.shrink_to_fit();
321 labels.shrink_to_fit();
322 pats.shrink_to_fit();
323 bindings.shrink_to_fit();
324 binding_owners.shrink_to_fit();
325 ident_hygiene.shrink_to_fit();
326 types.shrink_to_fit();
327 lifetimes.shrink_to_fit();
328
329 expr_map.shrink_to_fit();
330 expr_map_back.shrink_to_fit();
331 pat_map.shrink_to_fit();
332 pat_map_back.shrink_to_fit();
333 label_map.shrink_to_fit();
334 label_map_back.shrink_to_fit();
335 types_map_back.shrink_to_fit();
336 types_map.shrink_to_fit();
337 lifetime_map_back.shrink_to_fit();
338 lifetime_map.shrink_to_fit();
339 binding_definitions.shrink_to_fit();
340 field_map_back.shrink_to_fit();
341 pat_field_map_back.shrink_to_fit();
342 if let Some(template_map) = &mut template_map {
343 let FormatTemplate {
344 format_args_to_captures,
345 asm_to_captures,
346 implicit_capture_to_source,
347 } = &mut **template_map;
348 format_args_to_captures.shrink_to_fit();
349 asm_to_captures.shrink_to_fit();
350 implicit_capture_to_source.shrink_to_fit();
351 }
352 expansions.shrink_to_fit();
353
354 let has_exprs =
355 !exprs.is_empty() || !labels.is_empty() || !pats.is_empty() || !bindings.is_empty();
356
357 let store = {
358 let expr_only = if has_exprs {
359 Some(Box::new(ExpressionOnlyStore {
360 exprs,
361 pats,
362 bindings,
363 labels,
364 binding_owners,
365 block_scopes: block_scopes.into_boxed_slice(),
366 ident_hygiene,
367 }))
368 } else {
369 None
370 };
371 ExpressionStore { expr_only, types, lifetimes }
372 };
373
374 let source_map = {
375 let expr_only = if has_exprs || !expansions.is_empty() || !diagnostics.is_empty() {
376 Some(Box::new(ExpressionOnlySourceMap {
377 expr_map,
378 expr_map_back,
379 pat_map,
380 pat_map_back,
381 label_map,
382 label_map_back,
383 binding_definitions,
384 field_map_back,
385 pat_field_map_back,
386 template_map,
387 expansions,
388 diagnostics: ThinVec::from_iter(diagnostics),
389 }))
390 } else {
391 None
392 };
393 ExpressionStoreSourceMap {
394 expr_only,
395 types_map_back,
396 types_map,
397 lifetime_map_back,
398 lifetime_map,
399 }
400 };
401
402 (store, source_map)
403 }
404}
405
406impl ExpressionStore {
407 pub fn empty_singleton() -> (Arc<ExpressionStore>, Arc<ExpressionStoreSourceMap>) {
408 static EMPTY: LazyLock<(Arc<ExpressionStore>, Arc<ExpressionStoreSourceMap>)> =
409 LazyLock::new(|| {
410 let (store, source_map) = ExpressionStoreBuilder::default().finish();
411 (Arc::new(store), Arc::new(source_map))
412 });
413 EMPTY.clone()
414 }
415
416 pub fn blocks<'a>(
418 &'a self,
419 db: &'a dyn DefDatabase,
420 ) -> impl Iterator<Item = (BlockId, &'a DefMap)> + 'a {
421 self.expr_only
422 .as_ref()
423 .map(|it| &*it.block_scopes)
424 .unwrap_or_default()
425 .iter()
426 .map(move |&block| (block, block_def_map(db, block)))
427 }
428
429 pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
430 self.walk_pats(pat_id, &mut |pat| {
431 if let Pat::Bind { id, .. } = &self[pat] {
432 f(*id);
433 }
434 });
435 }
436
437 pub fn walk_pats_shallow(&self, pat_id: PatId, mut f: impl FnMut(PatId)) {
438 let pat = &self[pat_id];
439 match pat {
440 Pat::Range { .. }
441 | Pat::Lit(..)
442 | Pat::Path(..)
443 | Pat::ConstBlock(..)
444 | Pat::Wild
445 | Pat::Missing
446 | Pat::Expr(_) => {}
447 &Pat::Bind { subpat, .. } => {
448 if let Some(subpat) = subpat {
449 f(subpat);
450 }
451 }
452 Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => {
453 args.iter().copied().for_each(f);
454 }
455 Pat::Ref { pat, .. } => f(*pat),
456 Pat::Slice { prefix, slice, suffix } => {
457 let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter());
458 total_iter.copied().for_each(f);
459 }
460 Pat::Record { args, .. } => {
461 args.iter().for_each(|RecordFieldPat { pat, .. }| f(*pat));
462 }
463 Pat::Box { inner } => f(*inner),
464 }
465 }
466
467 pub fn walk_pats(&self, pat_id: PatId, f: &mut impl FnMut(PatId)) {
468 f(pat_id);
469 self.walk_pats_shallow(pat_id, |p| self.walk_pats(p, f));
470 }
471
472 pub fn is_binding_upvar(&self, binding: BindingId, relative_to: ExprId) -> bool {
473 let Some(expr_only) = &self.expr_only else { return false };
474 match expr_only.binding_owners.get(&binding) {
475 Some(it) => {
476 it.into_raw() < relative_to.into_raw()
479 }
480 None => true,
481 }
482 }
483
484 #[inline]
485 pub fn binding_owner(&self, id: BindingId) -> Option<ExprId> {
486 self.expr_only.as_ref()?.binding_owners.get(&id).copied()
487 }
488
489 pub fn walk_child_exprs(&self, expr_id: ExprId, mut f: impl FnMut(ExprId)) {
493 let expr = &self[expr_id];
494 match expr {
495 Expr::Continue { .. }
496 | Expr::Const(_)
497 | Expr::Missing
498 | Expr::Path(_)
499 | Expr::OffsetOf(_)
500 | Expr::Literal(_)
501 | Expr::Underscore => {}
502 Expr::InlineAsm(it) => it.operands.iter().for_each(|(_, op)| match op {
503 AsmOperand::In { expr, .. }
504 | AsmOperand::Out { expr: Some(expr), .. }
505 | AsmOperand::InOut { expr, .. }
506 | AsmOperand::Const(expr)
507 | AsmOperand::Label(expr) => f(*expr),
508 AsmOperand::SplitInOut { in_expr, out_expr, .. } => {
509 f(*in_expr);
510 if let Some(out_expr) = out_expr {
511 f(*out_expr);
512 }
513 }
514 AsmOperand::Out { expr: None, .. } | AsmOperand::Sym(_) => (),
515 }),
516 Expr::If { condition, then_branch, else_branch } => {
517 f(*condition);
518 f(*then_branch);
519 if let &Some(else_branch) = else_branch {
520 f(else_branch);
521 }
522 }
523 Expr::Let { expr, pat } => {
524 self.walk_exprs_in_pat(*pat, &mut f);
525 f(*expr);
526 }
527 Expr::Block { statements, tail, .. }
528 | Expr::Unsafe { statements, tail, .. }
529 | Expr::Async { statements, tail, .. } => {
530 for stmt in statements.iter() {
531 match stmt {
532 Statement::Let { initializer, else_branch, pat, .. } => {
533 if let &Some(expr) = initializer {
534 f(expr);
535 }
536 if let &Some(expr) = else_branch {
537 f(expr);
538 }
539 self.walk_exprs_in_pat(*pat, &mut f);
540 }
541 Statement::Expr { expr: expression, .. } => f(*expression),
542 Statement::Item(_) => (),
543 }
544 }
545 if let &Some(expr) = tail {
546 f(expr);
547 }
548 }
549 Expr::Loop { body, .. } => f(*body),
550 Expr::Call { callee, args, .. } => {
551 f(*callee);
552 args.iter().copied().for_each(f);
553 }
554 Expr::MethodCall { receiver, args, .. } => {
555 f(*receiver);
556 args.iter().copied().for_each(f);
557 }
558 Expr::Match { expr, arms } => {
559 f(*expr);
560 arms.iter().for_each(|arm| {
561 f(arm.expr);
562 self.walk_exprs_in_pat(arm.pat, &mut f);
563 });
564 }
565 Expr::Break { expr, .. }
566 | Expr::Return { expr }
567 | Expr::Yield { expr }
568 | Expr::Yeet { expr } => {
569 if let &Some(expr) = expr {
570 f(expr);
571 }
572 }
573 Expr::Become { expr } => f(*expr),
574 Expr::RecordLit { fields, spread, .. } => {
575 for field in fields.iter() {
576 f(field.expr);
577 }
578 if let &Some(expr) = spread {
579 f(expr);
580 }
581 }
582 Expr::Closure { body, .. } => {
583 f(*body);
584 }
585 Expr::BinaryOp { lhs, rhs, .. } => {
586 f(*lhs);
587 f(*rhs);
588 }
589 Expr::Range { lhs, rhs, .. } => {
590 if let &Some(lhs) = rhs {
591 f(lhs);
592 }
593 if let &Some(rhs) = lhs {
594 f(rhs);
595 }
596 }
597 Expr::Index { base, index, .. } => {
598 f(*base);
599 f(*index);
600 }
601 Expr::Field { expr, .. }
602 | Expr::Await { expr }
603 | Expr::Cast { expr, .. }
604 | Expr::Ref { expr, .. }
605 | Expr::UnaryOp { expr, .. }
606 | Expr::Box { expr } => {
607 f(*expr);
608 }
609 Expr::Tuple { exprs, .. } => exprs.iter().copied().for_each(f),
610 Expr::Array(a) => match a {
611 Array::ElementList { elements, .. } => elements.iter().copied().for_each(f),
612 Array::Repeat { initializer, repeat } => {
613 f(*initializer);
614 f(*repeat)
615 }
616 },
617 &Expr::Assignment { target, value } => {
618 self.walk_exprs_in_pat(target, &mut f);
619 f(value);
620 }
621 }
622 }
623
624 pub fn walk_child_exprs_without_pats(&self, expr_id: ExprId, mut f: impl FnMut(ExprId)) {
629 let expr = &self[expr_id];
630 match expr {
631 Expr::Continue { .. }
632 | Expr::Const(_)
633 | Expr::Missing
634 | Expr::Path(_)
635 | Expr::OffsetOf(_)
636 | Expr::Literal(_)
637 | Expr::Underscore => {}
638 Expr::InlineAsm(it) => it.operands.iter().for_each(|(_, op)| match op {
639 AsmOperand::In { expr, .. }
640 | AsmOperand::Out { expr: Some(expr), .. }
641 | AsmOperand::InOut { expr, .. }
642 | AsmOperand::Const(expr)
643 | AsmOperand::Label(expr) => f(*expr),
644 AsmOperand::SplitInOut { in_expr, out_expr, .. } => {
645 f(*in_expr);
646 if let Some(out_expr) = out_expr {
647 f(*out_expr);
648 }
649 }
650 AsmOperand::Out { expr: None, .. } | AsmOperand::Sym(_) => (),
651 }),
652 Expr::If { condition, then_branch, else_branch } => {
653 f(*condition);
654 f(*then_branch);
655 if let &Some(else_branch) = else_branch {
656 f(else_branch);
657 }
658 }
659 Expr::Let { expr, .. } => {
660 f(*expr);
661 }
662 Expr::Block { statements, tail, .. }
663 | Expr::Unsafe { statements, tail, .. }
664 | Expr::Async { statements, tail, .. } => {
665 for stmt in statements.iter() {
666 match stmt {
667 Statement::Let { initializer, else_branch, .. } => {
668 if let &Some(expr) = initializer {
669 f(expr);
670 }
671 if let &Some(expr) = else_branch {
672 f(expr);
673 }
674 }
675 Statement::Expr { expr: expression, .. } => f(*expression),
676 Statement::Item(_) => (),
677 }
678 }
679 if let &Some(expr) = tail {
680 f(expr);
681 }
682 }
683 Expr::Loop { body, .. } => f(*body),
684 Expr::Call { callee, args, .. } => {
685 f(*callee);
686 args.iter().copied().for_each(f);
687 }
688 Expr::MethodCall { receiver, args, .. } => {
689 f(*receiver);
690 args.iter().copied().for_each(f);
691 }
692 Expr::Match { expr, arms } => {
693 f(*expr);
694 arms.iter().map(|arm| arm.expr).for_each(f);
695 }
696 Expr::Break { expr, .. }
697 | Expr::Return { expr }
698 | Expr::Yield { expr }
699 | Expr::Yeet { expr } => {
700 if let &Some(expr) = expr {
701 f(expr);
702 }
703 }
704 Expr::Become { expr } => f(*expr),
705 Expr::RecordLit { fields, spread, .. } => {
706 for field in fields.iter() {
707 f(field.expr);
708 }
709 if let &Some(expr) = spread {
710 f(expr);
711 }
712 }
713 Expr::Closure { body, .. } => {
714 f(*body);
715 }
716 Expr::BinaryOp { lhs, rhs, .. } => {
717 f(*lhs);
718 f(*rhs);
719 }
720 Expr::Range { lhs, rhs, .. } => {
721 if let &Some(lhs) = rhs {
722 f(lhs);
723 }
724 if let &Some(rhs) = lhs {
725 f(rhs);
726 }
727 }
728 Expr::Index { base, index, .. } => {
729 f(*base);
730 f(*index);
731 }
732 Expr::Field { expr, .. }
733 | Expr::Await { expr }
734 | Expr::Cast { expr, .. }
735 | Expr::Ref { expr, .. }
736 | Expr::UnaryOp { expr, .. }
737 | Expr::Box { expr } => {
738 f(*expr);
739 }
740 Expr::Tuple { exprs, .. } => exprs.iter().copied().for_each(f),
741 Expr::Array(a) => match a {
742 Array::ElementList { elements, .. } => elements.iter().copied().for_each(f),
743 Array::Repeat { initializer, repeat } => {
744 f(*initializer);
745 f(*repeat)
746 }
747 },
748 &Expr::Assignment { target: _, value } => f(value),
749 }
750 }
751
752 pub fn walk_exprs_in_pat(&self, pat_id: PatId, f: &mut impl FnMut(ExprId)) {
753 self.walk_pats(pat_id, &mut |pat| {
754 if let Pat::Expr(expr) | Pat::ConstBlock(expr) = self[pat] {
755 f(expr);
756 }
757 });
758 }
759
760 #[inline]
761 #[track_caller]
762 fn assert_expr_only(&self) -> &ExpressionOnlyStore {
763 self.expr_only.as_ref().expect("should have `ExpressionStore::expr_only`")
764 }
765
766 fn binding_hygiene(&self, binding: BindingId) -> HygieneId {
767 self.assert_expr_only().bindings[binding].hygiene
768 }
769
770 pub fn expr_path_hygiene(&self, expr: ExprId) -> HygieneId {
771 self.assert_expr_only().ident_hygiene.get(&expr.into()).copied().unwrap_or(HygieneId::ROOT)
772 }
773
774 pub fn pat_path_hygiene(&self, pat: PatId) -> HygieneId {
775 self.assert_expr_only().ident_hygiene.get(&pat.into()).copied().unwrap_or(HygieneId::ROOT)
776 }
777
778 pub fn expr_or_pat_path_hygiene(&self, id: ExprOrPatId) -> HygieneId {
779 match id {
780 ExprOrPatId::ExprId(id) => self.expr_path_hygiene(id),
781 ExprOrPatId::PatId(id) => self.pat_path_hygiene(id),
782 }
783 }
784
785 #[inline]
786 pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
787 match &self.expr_only {
788 Some(it) => it.exprs.iter(),
789 None => const { &Arena::new() }.iter(),
790 }
791 }
792
793 #[inline]
794 pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
795 match &self.expr_only {
796 Some(it) => it.pats.iter(),
797 None => const { &Arena::new() }.iter(),
798 }
799 }
800
801 #[inline]
802 pub fn bindings(&self) -> impl Iterator<Item = (BindingId, &Binding)> {
803 match &self.expr_only {
804 Some(it) => it.bindings.iter(),
805 None => const { &Arena::new() }.iter(),
806 }
807 }
808}
809
810impl Index<ExprId> for ExpressionStore {
811 type Output = Expr;
812
813 #[inline]
814 fn index(&self, expr: ExprId) -> &Expr {
815 &self.assert_expr_only().exprs[expr]
816 }
817}
818
819impl Index<PatId> for ExpressionStore {
820 type Output = Pat;
821
822 #[inline]
823 fn index(&self, pat: PatId) -> &Pat {
824 &self.assert_expr_only().pats[pat]
825 }
826}
827
828impl Index<LabelId> for ExpressionStore {
829 type Output = Label;
830
831 #[inline]
832 fn index(&self, label: LabelId) -> &Label {
833 &self.assert_expr_only().labels[label]
834 }
835}
836
837impl Index<BindingId> for ExpressionStore {
838 type Output = Binding;
839
840 #[inline]
841 fn index(&self, b: BindingId) -> &Binding {
842 &self.assert_expr_only().bindings[b]
843 }
844}
845
846impl Index<TypeRefId> for ExpressionStore {
847 type Output = TypeRef;
848
849 #[inline]
850 fn index(&self, b: TypeRefId) -> &TypeRef {
851 &self.types[b]
852 }
853}
854
855impl Index<LifetimeRefId> for ExpressionStore {
856 type Output = LifetimeRef;
857
858 #[inline]
859 fn index(&self, b: LifetimeRefId) -> &LifetimeRef {
860 &self.lifetimes[b]
861 }
862}
863
864impl Index<PathId> for ExpressionStore {
865 type Output = Path;
866
867 #[inline]
868 fn index(&self, index: PathId) -> &Self::Output {
869 let TypeRef::Path(path) = &self[index.type_ref()] else {
870 unreachable!("`PathId` always points to `TypeRef::Path`");
871 };
872 path
873 }
874}
875
876impl ExpressionStoreSourceMap {
879 pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
880 match id {
881 ExprOrPatId::ExprId(id) => self.expr_syntax(id),
882 ExprOrPatId::PatId(id) => self.pat_syntax(id),
883 }
884 }
885
886 #[inline]
887 fn expr_or_synthetic(&self) -> Result<&ExpressionOnlySourceMap, SyntheticSyntax> {
888 self.expr_only.as_deref().ok_or(SyntheticSyntax)
889 }
890
891 #[inline]
892 fn expr_only(&self) -> Option<&ExpressionOnlySourceMap> {
893 self.expr_only.as_deref()
894 }
895
896 #[inline]
897 #[track_caller]
898 fn assert_expr_only(&self) -> &ExpressionOnlySourceMap {
899 self.expr_only.as_ref().expect("should have `ExpressionStoreSourceMap::expr_only`")
900 }
901
902 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprOrPatSource, SyntheticSyntax> {
903 self.expr_or_synthetic()?.expr_map_back.get(expr).cloned().ok_or(SyntheticSyntax)
904 }
905
906 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprOrPatId> {
907 let src = node.map(AstPtr::new);
908 self.expr_only()?.expr_map.get(&src).cloned()
909 }
910
911 pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<MacroCallId> {
912 let src = node.map(AstPtr::new);
913 self.expr_only()?.expansions.get(&src).cloned()
914 }
915
916 pub fn macro_calls(&self) -> impl Iterator<Item = (InFile<MacroCallPtr>, MacroCallId)> + '_ {
917 self.expr_only().into_iter().flat_map(|it| it.expansions.iter().map(|(&a, &b)| (a, b)))
918 }
919
920 pub fn pat_syntax(&self, pat: PatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
921 self.expr_or_synthetic()?.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
922 }
923
924 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<ExprOrPatId> {
925 self.expr_only()?.pat_map.get(&node.map(AstPtr::new)).cloned()
926 }
927
928 pub fn type_syntax(&self, id: TypeRefId) -> Result<TypeSource, SyntheticSyntax> {
929 self.types_map_back.get(id).cloned().ok_or(SyntheticSyntax)
930 }
931
932 pub fn node_type(&self, node: InFile<&ast::Type>) -> Option<TypeRefId> {
933 self.types_map.get(&node.map(AstPtr::new)).cloned()
934 }
935
936 pub fn label_syntax(&self, label: LabelId) -> LabelSource {
937 self.assert_expr_only().label_map_back[label]
938 }
939
940 pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] {
941 self.assert_expr_only().binding_definitions.get(binding).map_or(&[], Deref::deref)
942 }
943
944 pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
945 let src = node.map(AstPtr::new);
946 self.expr_only()?.label_map.get(&src).cloned()
947 }
948
949 pub fn field_syntax(&self, expr: ExprId) -> FieldSource {
950 self.assert_expr_only().field_map_back[&expr]
951 }
952
953 pub fn pat_field_syntax(&self, pat: PatId) -> PatFieldSource {
954 self.assert_expr_only().pat_field_map_back[&pat]
955 }
956
957 pub fn macro_expansion_expr(&self, node: InFile<&ast::MacroExpr>) -> Option<ExprOrPatId> {
958 let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::MacroExpr>).map(AstPtr::upcast);
959 self.expr_only()?.expr_map.get(&src).copied()
960 }
961
962 pub fn expansions(&self) -> impl Iterator<Item = (&InFile<MacroCallPtr>, &MacroCallId)> {
963 self.expr_only().into_iter().flat_map(|it| it.expansions.iter())
964 }
965
966 pub fn expansion(&self, node: InFile<&ast::MacroCall>) -> Option<MacroCallId> {
967 self.expr_only()?.expansions.get(&node.map(AstPtr::new)).copied()
968 }
969
970 pub fn implicit_format_args(
971 &self,
972 node: InFile<&ast::FormatArgsExpr>,
973 ) -> Option<(HygieneId, &[(syntax::TextRange, Name)])> {
974 let expr_only = self.expr_only()?;
975 let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
976 let (hygiene, names) = expr_only
977 .template_map
978 .as_ref()?
979 .format_args_to_captures
980 .get(&expr_only.expr_map.get(&src)?.as_expr()?)?;
981 Some((*hygiene, &**names))
982 }
983
984 pub fn format_args_implicit_capture(
985 &self,
986 capture_expr: ExprId,
987 ) -> Option<InFile<(ExprPtr, TextRange)>> {
988 self.expr_only()?
989 .template_map
990 .as_ref()?
991 .implicit_capture_to_source
992 .get(&capture_expr)
993 .copied()
994 }
995
996 pub fn asm_template_args(
997 &self,
998 node: InFile<&ast::AsmExpr>,
999 ) -> Option<(ExprId, &[Vec<(syntax::TextRange, usize)>])> {
1000 let expr_only = self.expr_only()?;
1001 let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
1002 let expr = expr_only.expr_map.get(&src)?.as_expr()?;
1003 Some(expr).zip(
1004 expr_only.template_map.as_ref()?.asm_to_captures.get(&expr).map(std::ops::Deref::deref),
1005 )
1006 }
1007
1008 pub fn diagnostics(&self) -> &[ExpressionStoreDiagnostics] {
1010 self.expr_only().map(|it| &*it.diagnostics).unwrap_or_default()
1011 }
1012}