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 borrow::Borrow,
14 ops::{Deref, Index},
15};
16
17use base_db::SourceDatabase;
18use cfg::{CfgExpr, CfgOptions};
19use either::Either;
20use hir_expand::{InFile, MacroCallId, mod_path::ModPath, name::Name};
21use la_arena::{Arena, ArenaMap};
22use smallvec::SmallVec;
23use span::{Edition, SyntaxContext};
24use syntax::{AstPtr, SyntaxNodePtr, ast};
25use thin_vec::ThinVec;
26use tt::TextRange;
27
28use crate::{
29 AdtId, BlockId, ExpressionStoreOwnerId, GenericDefId, SyntheticSyntax, ThinFxHashMap,
30 expr_store::path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
31 hir::{
32 Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, ExprOrPatIdPacked,
33 InlineAsm, Label, LabelId, MatchArm, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField,
34 RecordSpread, Statement,
35 },
36 nameres::{DefMap, block_def_map},
37 signatures::VariantFields,
38 type_ref::{
39 ArrayType, ConstRef, FnType, LifetimeRef, LifetimeRefId, PathId, RefType, TypeBound,
40 TypeRef, TypeRefId, UseArgRef,
41 },
42};
43
44pub use self::body::{Body, BodySourceMap};
45pub use self::lower::{
46 hir_assoc_type_binding_to_ast, hir_generic_arg_to_ast, hir_segment_to_ast_segment,
47};
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
51pub struct HygieneId(span::SyntaxContext);
52
53impl HygieneId {
54 pub const ROOT: Self = Self(span::SyntaxContext::root(Edition::Edition2015));
56
57 pub fn new(mut ctx: span::SyntaxContext) -> Self {
58 ctx.remove_root_edition();
60 Self(ctx)
61 }
62
63 pub(crate) fn syntax_context(self) -> SyntaxContext {
64 self.0
65 }
66
67 pub(crate) fn is_root(self) -> bool {
68 self.0.is_root()
69 }
70}
71
72pub type ExprPtr = AstPtr<ast::Expr>;
73pub type ExprSource = InFile<ExprPtr>;
74
75pub type PatPtr = AstPtr<ast::Pat>;
76pub type PatSource = InFile<PatPtr>;
77
78pub type LabelPtr = AstPtr<Either<ast::Label, ast::BlockExpr>>;
80pub type LabelSource = InFile<LabelPtr>;
81
82pub type FieldPtr = AstPtr<ast::RecordExprField>;
83pub type FieldSource = InFile<FieldPtr>;
84
85pub type PatFieldPtr = AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>;
86pub type PatFieldSource = InFile<PatFieldPtr>;
87
88pub type ExprOrPatPtr = AstPtr<Either<ast::Expr, ast::Pat>>;
89pub type ExprOrPatSource = InFile<ExprOrPatPtr>;
90
91pub type SelfParamPtr = AstPtr<ast::SelfParam>;
92pub type MacroCallPtr = AstPtr<ast::MacroCall>;
93
94pub type TypePtr = AstPtr<ast::Type>;
95pub type TypeSource = InFile<TypePtr>;
96
97pub type LifetimePtr = AstPtr<ast::Lifetime>;
98pub type LifetimeSource = InFile<LifetimePtr>;
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101struct ExprRoot {
102 root: ExprId,
103 exprs_end: ExprId,
107 pats_end: PatId,
108 bindings_end: BindingId,
109}
110
111#[derive(Debug, Clone, PartialEq, Eq)]
114struct ExpressionOnlyStore {
115 exprs: Arena<Expr>,
116 pats: Arena<Pat>,
117 bindings: Arena<Binding>,
118 labels: Arena<Label>,
119 binding_owners: ThinFxHashMap<BindingId, ExprId>,
122 block_scopes: Box<[BlockId]>,
124
125 ident_hygiene: ThinFxHashMap<ExprOrPatIdPacked, HygieneId>,
130
131 expr_roots: SmallVec<[ExprRoot; 1]>,
157}
158
159#[derive(Debug, Clone, PartialEq, Eq)]
160pub struct ExpressionStore {
161 expr_only: Option<Box<ExpressionOnlyStore>>,
162 pub types: Arena<TypeRef>,
163 pub lifetimes: Arena<LifetimeRef>,
164}
165
166#[derive(Debug, Eq, Default)]
167struct ExpressionOnlySourceMap {
168 expr_map: ThinFxHashMap<ExprSource, ExprOrPatIdPacked>,
171 expr_map_back: ArenaMap<ExprId, ExprOrPatSource>,
172
173 pat_map: ThinFxHashMap<PatSource, ExprOrPatIdPacked>,
174 pat_map_back: ArenaMap<PatId, ExprOrPatSource>,
175
176 label_map: ThinFxHashMap<LabelSource, LabelId>,
177 label_map_back: ArenaMap<LabelId, LabelSource>,
178
179 binding_definitions:
180 ArenaMap<BindingId, SmallVec<[PatId; 2 * size_of::<usize>() / size_of::<PatId>()]>>,
181
182 field_map_back: ThinFxHashMap<ExprId, FieldSource>,
185 pat_field_map_back: ThinFxHashMap<PatId, PatFieldSource>,
186
187 template_map: Option<Box<FormatTemplate>>,
188
189 expansions: ThinFxHashMap<InFile<MacroCallPtr>, MacroCallId>,
190
191 diagnostics: ThinVec<ExpressionStoreDiagnostics>,
197}
198
199impl PartialEq for ExpressionOnlySourceMap {
200 fn eq(&self, other: &Self) -> bool {
201 let Self {
205 expr_map: _,
206 expr_map_back,
207 pat_map: _,
208 pat_map_back,
209 label_map: _,
210 label_map_back,
211 binding_definitions: _,
213 field_map_back: _,
215 pat_field_map_back: _,
217 template_map,
218 expansions,
219 diagnostics,
220 } = self;
221 *expr_map_back == other.expr_map_back
222 && *pat_map_back == other.pat_map_back
223 && *label_map_back == other.label_map_back
224 && *template_map == other.template_map
225 && *expansions == other.expansions
226 && *diagnostics == other.diagnostics
227 }
228}
229
230#[derive(Debug, Eq, Default)]
231pub struct ExpressionStoreSourceMap {
232 expr_only: Option<Box<ExpressionOnlySourceMap>>,
233
234 types_map_back: ArenaMap<TypeRefId, TypeSource>,
235 types_map: ThinFxHashMap<TypeSource, TypeRefId>,
236
237 lifetime_map_back: ArenaMap<LifetimeRefId, LifetimeSource>,
238 #[expect(
239 unused,
240 reason = "this is here for completeness, and maybe we'll need it in the future"
241 )]
242 lifetime_map: ThinFxHashMap<LifetimeSource, LifetimeRefId>,
243}
244
245impl PartialEq for ExpressionStoreSourceMap {
246 fn eq(&self, other: &Self) -> bool {
247 let Self { expr_only, types_map_back, types_map: _, lifetime_map_back, lifetime_map: _ } =
251 self;
252 *expr_only == other.expr_only
253 && *types_map_back == other.types_map_back
254 && *lifetime_map_back == other.lifetime_map_back
255 }
256}
257
258#[derive(Debug, Eq, PartialEq, Default)]
260pub struct ExpressionStoreBuilder {
261 pub exprs: Arena<Expr>,
262 pub pats: Arena<Pat>,
263 pub bindings: Arena<Binding>,
264 pub labels: Arena<Label>,
265 pub lifetimes: Arena<LifetimeRef>,
266 pub binding_owners: ThinFxHashMap<BindingId, ExprId>,
267 pub types: Arena<TypeRef>,
268 block_scopes: Vec<BlockId>,
269 ident_hygiene: ThinFxHashMap<ExprOrPatIdPacked, HygieneId>,
270 inference_roots: Option<SmallVec<[ExprRoot; 1]>>,
271
272 expr_map: ThinFxHashMap<ExprSource, ExprOrPatIdPacked>,
275 expr_map_back: ArenaMap<ExprId, ExprOrPatSource>,
276
277 pat_map: ThinFxHashMap<PatSource, ExprOrPatIdPacked>,
278 pat_map_back: ArenaMap<PatId, ExprOrPatSource>,
279
280 label_map: ThinFxHashMap<LabelSource, LabelId>,
281 label_map_back: ArenaMap<LabelId, LabelSource>,
282
283 types_map_back: ArenaMap<TypeRefId, TypeSource>,
284 types_map: ThinFxHashMap<TypeSource, TypeRefId>,
285
286 lifetime_map_back: ArenaMap<LifetimeRefId, LifetimeSource>,
287 lifetime_map: ThinFxHashMap<LifetimeSource, LifetimeRefId>,
288
289 binding_definitions:
290 ArenaMap<BindingId, SmallVec<[PatId; 2 * size_of::<usize>() / size_of::<PatId>()]>>,
291
292 field_map_back: ThinFxHashMap<ExprId, FieldSource>,
295 pat_field_map_back: ThinFxHashMap<PatId, PatFieldSource>,
296
297 template_map: Option<Box<FormatTemplate>>,
298
299 expansions: ThinFxHashMap<InFile<MacroCallPtr>, MacroCallId>,
300
301 pub(crate) diagnostics: Vec<ExpressionStoreDiagnostics>,
307}
308
309#[derive(Default, Debug, Eq, PartialEq)]
310struct FormatTemplate {
311 format_args_to_captures: ThinFxHashMap<ExprId, (HygieneId, Vec<(syntax::TextRange, Name)>)>,
313 asm_to_captures: ThinFxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>,
315 implicit_capture_to_source: ThinFxHashMap<ExprId, InFile<(ExprPtr, TextRange)>>,
321}
322
323#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
324pub enum MissingBodyItemKind {
325 AssocConst,
326 AssocType,
327 Const,
328 Static,
329 TypeAlias,
330}
331
332#[derive(Debug, Eq, PartialEq)]
333pub enum ExpressionStoreDiagnostics {
334 InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
335 UnresolvedMacroCall { node: InFile<MacroCallPtr>, path: ModPath },
336 UnreachableLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
337 AwaitOutsideOfAsync { node: InFile<AstPtr<ast::AwaitExpr>>, location: String },
338 UndeclaredLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
339 PatternArgInExternFn { node: InFile<AstPtr<ast::Pat>> },
340 FruInDestructuringAssignment { node: InFile<AstPtr<ast::Expr>> },
341 MissingBody { node: InFile<SyntaxNodePtr>, kind: MissingBodyItemKind },
342}
343
344impl ExpressionStoreBuilder {
345 pub fn finish(self) -> (ExpressionStore, ExpressionStoreSourceMap) {
346 let Self {
347 block_scopes,
348 mut exprs,
349 mut labels,
350 mut pats,
351 mut bindings,
352 mut binding_owners,
353 mut ident_hygiene,
354 inference_roots: mut expr_roots,
355 mut types,
356 mut lifetimes,
357
358 mut expr_map,
359 mut expr_map_back,
360 mut pat_map,
361 mut pat_map_back,
362 mut label_map,
363 mut label_map_back,
364 mut types_map_back,
365 mut types_map,
366 mut lifetime_map_back,
367 mut lifetime_map,
368 mut binding_definitions,
369 mut field_map_back,
370 mut pat_field_map_back,
371 mut template_map,
372 mut expansions,
373 diagnostics,
374 } = self;
375 exprs.shrink_to_fit();
376 labels.shrink_to_fit();
377 pats.shrink_to_fit();
378 bindings.shrink_to_fit();
379 binding_owners.shrink_to_fit();
380 ident_hygiene.shrink_to_fit();
381 types.shrink_to_fit();
382 lifetimes.shrink_to_fit();
383
384 expr_map.shrink_to_fit();
385 expr_map_back.shrink_to_fit();
386 pat_map.shrink_to_fit();
387 pat_map_back.shrink_to_fit();
388 label_map.shrink_to_fit();
389 label_map_back.shrink_to_fit();
390 types_map_back.shrink_to_fit();
391 types_map.shrink_to_fit();
392 lifetime_map_back.shrink_to_fit();
393 lifetime_map.shrink_to_fit();
394 binding_definitions.shrink_to_fit();
395 field_map_back.shrink_to_fit();
396 pat_field_map_back.shrink_to_fit();
397 if let Some(template_map) = &mut template_map {
398 let FormatTemplate {
399 format_args_to_captures,
400 asm_to_captures,
401 implicit_capture_to_source,
402 } = &mut **template_map;
403 format_args_to_captures.shrink_to_fit();
404 asm_to_captures.shrink_to_fit();
405 implicit_capture_to_source.shrink_to_fit();
406 }
407 expansions.shrink_to_fit();
408
409 let has_exprs =
410 !exprs.is_empty() || !labels.is_empty() || !pats.is_empty() || !bindings.is_empty();
411
412 let store = {
413 let expr_only = if has_exprs {
414 if let Some(expr_roots) = &mut expr_roots {
415 expr_roots.shrink_to_fit();
416 }
417 Some(Box::new(ExpressionOnlyStore {
418 exprs,
419 pats,
420 bindings,
421 labels,
422 binding_owners,
423 block_scopes: block_scopes.into_boxed_slice(),
424 ident_hygiene,
425 expr_roots: expr_roots
426 .expect("should always finish with a `Some(_)` expr_roots"),
427 }))
428 } else {
429 None
430 };
431 ExpressionStore { expr_only, types, lifetimes }
432 };
433
434 let source_map = {
435 let expr_only = if has_exprs || !expansions.is_empty() || !diagnostics.is_empty() {
436 Some(Box::new(ExpressionOnlySourceMap {
437 expr_map,
438 expr_map_back,
439 pat_map,
440 pat_map_back,
441 label_map,
442 label_map_back,
443 binding_definitions,
444 field_map_back,
445 pat_field_map_back,
446 template_map,
447 expansions,
448 diagnostics: ThinVec::from_iter(diagnostics),
449 }))
450 } else {
451 None
452 };
453 ExpressionStoreSourceMap {
454 expr_only,
455 types_map_back,
456 types_map,
457 lifetime_map_back,
458 lifetime_map,
459 }
460 };
461
462 (store, source_map)
463 }
464}
465
466impl ExpressionStore {
467 const EMPTY: &ExpressionStore =
468 &ExpressionStore { expr_only: None, types: Arena::new(), lifetimes: Arena::new() };
469
470 #[inline]
471 pub fn empty() -> &'static ExpressionStore {
472 ExpressionStore::EMPTY
473 }
474
475 pub fn of(db: &dyn SourceDatabase, def: ExpressionStoreOwnerId) -> &ExpressionStore {
476 match def {
477 ExpressionStoreOwnerId::Signature(def) => {
478 use crate::signatures::{
479 ConstSignature, EnumSignature, FunctionSignature, ImplSignature,
480 StaticSignature, StructSignature, TraitSignature, TypeAliasSignature,
481 UnionSignature,
482 };
483 match def {
484 GenericDefId::AdtId(AdtId::EnumId(id)) => &EnumSignature::of(db, id).store,
485 GenericDefId::AdtId(AdtId::StructId(id)) => &StructSignature::of(db, id).store,
486 GenericDefId::AdtId(AdtId::UnionId(id)) => &UnionSignature::of(db, id).store,
487 GenericDefId::ConstId(id) => &ConstSignature::of(db, id).store,
488 GenericDefId::FunctionId(id) => &FunctionSignature::of(db, id).store,
489 GenericDefId::ImplId(id) => &ImplSignature::of(db, id).store,
490 GenericDefId::StaticId(id) => &StaticSignature::of(db, id).store,
491 GenericDefId::TraitId(id) => &TraitSignature::of(db, id).store,
492 GenericDefId::TypeAliasId(id) => &TypeAliasSignature::of(db, id).store,
493 }
494 }
495 ExpressionStoreOwnerId::Body(body) => &Body::of(db, body).store,
496 ExpressionStoreOwnerId::VariantFields(variant_id) => {
497 &VariantFields::of(db, variant_id).store
498 }
499 }
500 }
501
502 pub fn with_source_map(
503 db: &dyn SourceDatabase,
504 def: ExpressionStoreOwnerId,
505 ) -> (&ExpressionStore, &ExpressionStoreSourceMap) {
506 match def {
507 ExpressionStoreOwnerId::Signature(def) => {
508 use crate::signatures::{
509 ConstSignature, EnumSignature, FunctionSignature, ImplSignature,
510 StaticSignature, StructSignature, TraitSignature, TypeAliasSignature,
511 UnionSignature,
512 };
513 match def {
514 GenericDefId::AdtId(AdtId::EnumId(id)) => {
515 let sig = EnumSignature::with_source_map(db, id);
516 (&sig.0.store, &sig.1)
517 }
518 GenericDefId::AdtId(AdtId::StructId(id)) => {
519 let sig = StructSignature::with_source_map(db, id);
520 (&sig.0.store, &sig.1)
521 }
522 GenericDefId::AdtId(AdtId::UnionId(id)) => {
523 let sig = UnionSignature::with_source_map(db, id);
524 (&sig.0.store, &sig.1)
525 }
526 GenericDefId::ConstId(id) => {
527 let sig = ConstSignature::with_source_map(db, id);
528 (&sig.0.store, &sig.1)
529 }
530 GenericDefId::FunctionId(id) => {
531 let sig = FunctionSignature::with_source_map(db, id);
532 (&sig.0.store, &sig.1)
533 }
534 GenericDefId::ImplId(id) => {
535 let sig = ImplSignature::with_source_map(db, id);
536 (&sig.0.store, &sig.1)
537 }
538 GenericDefId::StaticId(id) => {
539 let sig = StaticSignature::with_source_map(db, id);
540 (&sig.0.store, &sig.1)
541 }
542 GenericDefId::TraitId(id) => {
543 let sig = TraitSignature::with_source_map(db, id);
544 (&sig.0.store, &sig.1)
545 }
546 GenericDefId::TypeAliasId(id) => {
547 let sig = TypeAliasSignature::with_source_map(db, id);
548 (&sig.0.store, &sig.1)
549 }
550 }
551 }
552 ExpressionStoreOwnerId::Body(body) => {
553 let (store, sm) = Body::with_source_map(db, body);
554 (&store.store, &sm.store)
555 }
556 ExpressionStoreOwnerId::VariantFields(variant_id) => {
557 let (store, sm) = VariantFields::with_source_map(db, variant_id);
558 (&store.store, sm)
559 }
560 }
561 }
562
563 pub fn expr_roots(&self) -> impl DoubleEndedIterator<Item = ExprId> {
565 self.expr_only
566 .as_ref()
567 .map_or(&[][..], |expr_only| &expr_only.expr_roots)
568 .iter()
569 .map(|root| root.root)
570 }
571
572 fn find_root_for(
573 &self,
574 mut get: impl FnMut(&ExprRoot) -> la_arena::RawIdx,
575 find: la_arena::RawIdx,
576 ) -> ExprId {
577 let expr_only = self.assert_expr_only();
578 let find = find.into_u32();
579 let entry = expr_only.expr_roots.partition_point(|root| get(root).into_u32() <= find);
580 expr_only.expr_roots[entry].root
581 }
582
583 pub fn find_root_for_expr(&self, expr: ExprId) -> ExprId {
584 self.find_root_for(|root| root.exprs_end.into_raw(), expr.into_raw())
585 }
586
587 pub fn find_root_for_pat(&self, pat: PatId) -> ExprId {
588 self.find_root_for(|root| root.pats_end.into_raw(), pat.into_raw())
589 }
590
591 pub fn find_root_for_binding(&self, binding: BindingId) -> ExprId {
592 self.find_root_for(|root| root.bindings_end.into_raw(), binding.into_raw())
593 }
594
595 pub fn blocks<'a>(
597 &'a self,
598 db: &'a dyn SourceDatabase,
599 ) -> impl Iterator<Item = (BlockId, &'a DefMap)> + 'a {
600 self.expr_only
601 .as_ref()
602 .map(|it| &*it.block_scopes)
603 .unwrap_or_default()
604 .iter()
605 .map(move |&block| (block, block_def_map(db, block)))
606 }
607
608 pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
609 self.walk_pats(pat_id, &mut |pat| {
610 if let Pat::Bind { id, .. } = &self[pat] {
611 f(*id);
612 }
613 });
614 }
615
616 pub fn visit_pat_children(&self, pat_id: PatId, mut visitor: impl StoreVisitor) {
617 let pat = &self[pat_id];
620 match pat {
621 Pat::Range { start, end, range_type: _ } => {
622 visitor.on_expr_opt(*start);
623 visitor.on_expr_opt(*end);
624 }
625 Pat::Lit(expr) | Pat::Expr(expr) => visitor.on_expr(*expr),
626 Pat::Path(path) => visitor.on_path(path),
627 Pat::Wild | Pat::Missing | Pat::Rest | Pat::NotNull => {}
628 &Pat::Bind { subpat, id: _ } => visitor.on_pat_opt(subpat),
629 Pat::Or(args) | Pat::Tuple { args, ellipsis: _ } => visitor.on_pats(args),
630 Pat::TupleStruct { args, ellipsis: _, path } => {
631 visitor.on_pats(args);
632 visitor.on_path(path);
633 }
634 Pat::Ref { pat, mutability: _ } => visitor.on_pat(*pat),
635 Pat::Slice { prefix, slice, suffix } => {
636 visitor.on_pats(prefix);
637 visitor.on_pat_opt(*slice);
638 visitor.on_pats(suffix);
639 }
640 Pat::Record { args, ellipsis: _, path } => {
641 args.iter().for_each(|RecordFieldPat { pat, name: _ }| visitor.on_pat(*pat));
642 visitor.on_path(path);
643 }
644 Pat::Box { inner } | Pat::Deref { inner } => visitor.on_pat(*inner),
645 }
646 }
647
648 pub fn walk_pats_shallow(&self, pat_id: PatId, f: impl FnMut(PatId)) {
649 return self.visit_pat_children(pat_id, Visitor(f));
650
651 struct Visitor<F>(F);
652
653 impl<F: FnMut(PatId)> StoreVisitor for Visitor<F> {
654 fn on_pat(&mut self, pat: PatId) {
655 (self.0)(pat);
656 }
657 }
658 }
659
660 pub fn walk_pats(&self, pat_id: PatId, f: &mut impl FnMut(PatId)) {
661 f(pat_id);
662 self.walk_pats_shallow(pat_id, |p| self.walk_pats(p, f));
663 }
664
665 #[inline]
666 pub fn binding_owner(&self, id: BindingId) -> Option<ExprId> {
667 self.expr_only.as_ref()?.binding_owners.get(&id).copied()
668 }
669
670 pub fn visit_expr_children(&self, expr_id: ExprId, mut visitor: impl StoreVisitor) {
671 match &self[expr_id] {
674 Expr::OffsetOf(OffsetOf { container, fields: _ }) => visitor.on_type(*container),
675 Expr::Path(path) => visitor.on_path(path),
676 Expr::Continue { label: _ } | Expr::Missing | Expr::Literal(_) | Expr::Underscore => {}
677 Expr::InlineAsm(InlineAsm { operands, options: _, kind: _ }) => {
678 operands.iter().for_each(|(_, op)| match op {
679 AsmOperand::In { expr, reg: _ }
680 | AsmOperand::Out { expr: Some(expr), late: _, reg: _ }
681 | AsmOperand::InOut { expr, late: _, reg: _ }
682 | AsmOperand::Const(expr)
683 | AsmOperand::Label(expr) => visitor.on_expr(*expr),
684 AsmOperand::SplitInOut { in_expr, out_expr, late: _, reg: _ } => {
685 visitor.on_expr(*in_expr);
686 visitor.on_expr_opt(*out_expr);
687 }
688 AsmOperand::Out { expr: None, late: _, reg: _ } | AsmOperand::Sym(_) => (),
689 })
690 }
691 Expr::If { condition, then_branch, else_branch } => {
692 visitor.on_expr(*condition);
693 visitor.on_expr(*then_branch);
694 visitor.on_expr_opt(*else_branch);
695 }
696 Expr::Let { expr, pat } => {
697 visitor.on_pat(*pat);
698 visitor.on_expr(*expr);
699 }
700 Expr::Block { statements, tail, id: _, label: _, unsafe_: _ } => {
701 for stmt in statements {
702 match stmt {
703 Statement::Let { initializer, else_branch, pat, type_ref } => {
704 visitor.on_expr_opt(*initializer);
705 visitor.on_expr_opt(*else_branch);
706 visitor.on_pat(*pat);
707 visitor.on_type_opt(*type_ref);
708 }
709 Statement::Expr { expr: expression, has_semi: _ } => {
710 visitor.on_expr(*expression)
711 }
712 Statement::Item(_) => (),
713 }
714 }
715 visitor.on_expr_opt(*tail);
716 }
717 Expr::Loop { body, label: _, source: _ } => visitor.on_expr(*body),
718 Expr::Call { callee, args } => {
719 visitor.on_expr(*callee);
720 visitor.on_exprs(args);
721 }
722 Expr::MethodCall { receiver, args, generic_args, method_name: _ } => {
723 visitor.on_expr(*receiver);
724 visitor.on_exprs(args);
725 visitor.on_generic_args_opt(generic_args);
726 }
727 Expr::Match { expr, arms } => {
728 visitor.on_expr(*expr);
729 arms.iter().for_each(|MatchArm { pat, guard, expr }| {
730 visitor.on_expr(*expr);
731 visitor.on_expr_opt(*guard);
732 visitor.on_pat(*pat);
733 });
734 }
735 Expr::Break { expr, label: _ }
736 | Expr::Return { expr }
737 | Expr::Yield { expr }
738 | Expr::Yeet { expr } => visitor.on_expr_opt(*expr),
739 Expr::Become { expr } => visitor.on_expr(*expr),
740 Expr::RecordLit { fields, spread, path } => {
741 for RecordLitField { name: _, expr } in fields.iter() {
742 visitor.on_expr(*expr);
743 }
744 match spread {
745 RecordSpread::Expr(expr) => visitor.on_expr(*expr),
746 RecordSpread::None | RecordSpread::FieldDefaults => {}
747 }
748 visitor.on_path(path);
749 }
750 Expr::Closure { body, args, arg_types, ret_type, capture_by: _, closure_kind: _ } => {
751 visitor.on_expr(*body);
752 visitor.on_pats(args);
753 arg_types.iter().for_each(|arg_type| visitor.on_type_opt(*arg_type));
754 visitor.on_type_opt(*ret_type);
755 }
756 Expr::BinaryOp { lhs, rhs, op: _ } => {
757 visitor.on_expr(*lhs);
758 visitor.on_expr(*rhs);
759 }
760 Expr::Index { base, index } => {
761 visitor.on_expr(*base);
762 visitor.on_expr(*index);
763 }
764 Expr::Cast { expr, type_ref } => {
765 visitor.on_expr(*expr);
766 visitor.on_type(*type_ref);
767 }
768 Expr::Field { expr, name: _ }
769 | Expr::Await { expr }
770 | Expr::Ref { expr, mutability: _, rawness: _ }
771 | Expr::UnaryOp { expr, op: _ } => visitor.on_expr(*expr),
772 Expr::Const(expr) => visitor.on_anon_const_expr(*expr),
773 Expr::Tuple { exprs } => visitor.on_exprs(exprs),
774 Expr::Array(a) => match a {
775 Array::ElementList { elements } => visitor.on_exprs(elements),
776 Array::Repeat { initializer, repeat } => {
777 visitor.on_expr(*initializer);
778 visitor.on_anon_const_expr(*repeat)
779 }
780 },
781 &Expr::Assignment { target, value } => {
782 visitor.on_pat(target);
783 visitor.on_expr(value);
784 }
785 Expr::IncludeBytes => {}
786 }
787 }
788
789 pub fn walk_child_exprs(&self, expr_id: ExprId, callback: impl FnMut(ExprId)) {
791 return self.visit_expr_children(expr_id, Visitor { callback, store: self });
792
793 struct Visitor<'a, F> {
794 callback: F,
795 store: &'a ExpressionStore,
796 }
797
798 impl<F: FnMut(ExprId)> StoreVisitor for Visitor<'_, F> {
799 fn on_expr(&mut self, expr: ExprId) {
800 (self.callback)(expr);
801 }
802
803 fn on_pat(&mut self, pat: PatId) {
804 self.store.walk_exprs_in_pat(pat, &mut self.callback);
805 }
806 }
807 }
808
809 pub fn walk_child_exprs_without_pats(&self, expr_id: ExprId, callback: impl FnMut(ExprId)) {
812 return self.visit_expr_children(expr_id, Visitor { callback });
813
814 struct Visitor<F> {
815 callback: F,
816 }
817
818 impl<F: FnMut(ExprId)> StoreVisitor for Visitor<F> {
819 fn on_expr(&mut self, expr: ExprId) {
820 (self.callback)(expr);
821 }
822 }
823 }
824
825 pub fn walk_exprs_in_pat(&self, pat_id: PatId, callback: impl FnMut(ExprId)) {
826 return Visitor { callback, store: self }.on_pat(pat_id);
827
828 struct Visitor<'a, F> {
829 callback: F,
830 store: &'a ExpressionStore,
831 }
832
833 impl<F: FnMut(ExprId)> StoreVisitor for Visitor<'_, F> {
834 fn on_expr(&mut self, expr: ExprId) {
835 (self.callback)(expr);
836 }
837
838 fn on_pat(&mut self, pat: PatId) {
839 self.store.visit_pat_children(pat, self);
840 }
841 }
842 }
843
844 pub fn visit_type_ref_children(&self, type_ref: TypeRefId, mut visitor: impl StoreVisitor) {
845 match &self[type_ref] {
846 TypeRef::Never | TypeRef::Placeholder | TypeRef::TypeParam(_) | TypeRef::Error => {}
847 &TypeRef::PatternType(ty, pat) => {
848 visitor.on_type(ty);
849 visitor.on_pat(pat)
850 }
851 TypeRef::Tuple(types) => visitor.on_types(types),
852 TypeRef::Path(path) => visitor.on_path(path),
853 TypeRef::RawPtr(inner, _) | TypeRef::Slice(inner) => visitor.on_type(*inner),
854 TypeRef::Reference(ref_type) => {
855 let RefType { ty, lifetime, mutability: _ } = &**ref_type;
856 visitor.on_type(*ty);
857 visitor.on_lifetime_opt(*lifetime);
858 }
859 TypeRef::Array(ArrayType { ty, len: ConstRef { expr: len } }) => {
860 visitor.on_type(*ty);
861 visitor.on_anon_const_expr(*len);
862 }
863 TypeRef::Fn(fn_type) => {
864 let FnType { params, is_varargs: _, is_unsafe: _, abi: _, binder: _ } = &**fn_type;
865 params.iter().for_each(|(_, param_ty)| visitor.on_type(*param_ty));
866 }
867 TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
868 visitor.on_type_bounds(bounds)
869 }
870 }
871 }
872
873 #[inline]
874 #[track_caller]
875 fn assert_expr_only(&self) -> &ExpressionOnlyStore {
876 self.expr_only.as_ref().expect("should have `ExpressionStore::expr_only`")
877 }
878
879 fn binding_hygiene(&self, binding: BindingId) -> HygieneId {
880 self.assert_expr_only().bindings[binding].hygiene
881 }
882
883 pub fn expr_path_hygiene(&self, expr: ExprId) -> HygieneId {
884 self.assert_expr_only().ident_hygiene.get(&expr.into()).copied().unwrap_or(HygieneId::ROOT)
885 }
886
887 pub fn pat_path_hygiene(&self, pat: PatId) -> HygieneId {
888 self.assert_expr_only().ident_hygiene.get(&pat.into()).copied().unwrap_or(HygieneId::ROOT)
889 }
890
891 pub fn expr_or_pat_path_hygiene(&self, id: ExprOrPatId) -> HygieneId {
892 match id {
893 ExprOrPatId::ExprId(id) => self.expr_path_hygiene(id),
894 ExprOrPatId::PatId(id) => self.pat_path_hygiene(id),
895 }
896 }
897
898 #[inline]
899 pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
900 match &self.expr_only {
901 Some(it) => it.exprs.iter(),
902 None => const { &Arena::new() }.iter(),
903 }
904 }
905
906 #[inline]
907 pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
908 match &self.expr_only {
909 Some(it) => it.pats.iter(),
910 None => const { &Arena::new() }.iter(),
911 }
912 }
913
914 #[inline]
915 pub fn bindings(&self) -> impl Iterator<Item = (BindingId, &Binding)> {
916 match &self.expr_only {
917 Some(it) => it.bindings.iter(),
918 None => const { &Arena::new() }.iter(),
919 }
920 }
921
922 #[inline]
924 pub fn coroutine_for_closure(coroutine_closure: ExprId) -> ExprId {
925 ExprId::from_raw(la_arena::RawIdx::from_u32(coroutine_closure.into_raw().into_u32() - 1))
927 }
928
929 #[inline]
931 pub fn closure_for_coroutine(coroutine: ExprId) -> ExprId {
932 ExprId::from_raw(la_arena::RawIdx::from_u32(coroutine.into_raw().into_u32() + 1))
934 }
935}
936
937pub trait StoreVisitor: Sized {
938 fn on_expr(&mut self, expr: ExprId) {
939 let _ = expr;
940 }
941 fn on_anon_const_expr(&mut self, expr: ExprId) {
942 self.on_expr(expr);
943 }
944 fn on_pat(&mut self, pat: PatId) {
945 let _ = pat;
946 }
947 fn on_type(&mut self, ty: TypeRefId) {
948 let _ = ty;
949 }
950 fn on_lifetime(&mut self, lifetime: LifetimeRefId) {
951 let _ = lifetime;
952 }
953
954 fn on_generic_args(&mut self, args: &GenericArgs) {
955 visit_generic_args(self, args);
956 }
957}
958
959pub(crate) fn visit_generic_args<V: StoreVisitor>(visitor: &mut V, args: &GenericArgs) {
960 let GenericArgs { args, bindings, parenthesized: _, has_self_type: _ } = args;
961 for arg in args {
962 match arg {
963 GenericArg::Type(arg) => visitor.on_type(*arg),
964 GenericArg::Const(ConstRef { expr }) => visitor.on_anon_const_expr(*expr),
965 GenericArg::Lifetime(arg) => visitor.on_lifetime(*arg),
966 }
967 }
968 for AssociatedTypeBinding { name: _, args, type_ref, bounds } in bindings {
969 visitor.on_generic_args_opt(args);
970 visitor.on_type_opt(*type_ref);
971 visitor.on_type_bounds(bounds);
972 }
973}
974
975impl<V: StoreVisitor> StoreVisitor for &mut V {
976 fn on_expr(&mut self, expr: ExprId) {
977 V::on_expr(self, expr);
978 }
979 fn on_anon_const_expr(&mut self, expr: ExprId) {
980 V::on_anon_const_expr(self, expr);
981 }
982 fn on_pat(&mut self, pat: PatId) {
983 V::on_pat(self, pat);
984 }
985 fn on_type(&mut self, ty: TypeRefId) {
986 V::on_type(self, ty);
987 }
988 fn on_lifetime(&mut self, lifetime: LifetimeRefId) {
989 V::on_lifetime(self, lifetime);
990 }
991
992 fn on_generic_args(&mut self, args: &GenericArgs) {
993 V::on_generic_args(self, args);
994 }
995}
996
997pub trait StoreVisitorExt: StoreVisitor {
998 fn on_type_bound(&mut self, bound: &TypeBound) {
999 match bound {
1000 TypeBound::Path(path_id, _) => self.on_type(path_id.type_ref()),
1001 TypeBound::ForLifetime(_, path_id) => self.on_type(path_id.type_ref()),
1002 TypeBound::Lifetime(lifetime) => self.on_lifetime(*lifetime),
1003 TypeBound::Use(args) => {
1004 for arg in args {
1005 match arg {
1006 UseArgRef::Lifetime(lifetime) => self.on_lifetime(*lifetime),
1007 UseArgRef::Name(_) => {}
1008 }
1009 }
1010 }
1011 TypeBound::Error => {}
1012 }
1013 }
1014
1015 fn on_path(&mut self, path: &Path) {
1016 match path {
1017 Path::Normal(path) => {
1018 let NormalPath { generic_args, type_anchor, mod_path: _ } = &**path;
1019 generic_args.iter().for_each(|generic_arg| self.on_generic_args_opt(generic_arg));
1020 self.on_type_opt(*type_anchor);
1021 }
1022 Path::BarePath(_) | Path::LangItem(..) => {}
1023 }
1024 }
1025
1026 fn on_expr_opt(&mut self, expr: Option<ExprId>) {
1027 if let Some(expr) = expr {
1028 self.on_expr(expr);
1029 }
1030 }
1031 fn on_pat_opt(&mut self, pat: Option<PatId>) {
1032 if let Some(pat) = pat {
1033 self.on_pat(pat);
1034 }
1035 }
1036 fn on_type_opt(&mut self, ty: Option<TypeRefId>) {
1037 if let Some(ty) = ty {
1038 self.on_type(ty);
1039 }
1040 }
1041 fn on_lifetime_opt(&mut self, lifetime: Option<LifetimeRefId>) {
1042 if let Some(lifetime) = lifetime {
1043 self.on_lifetime(lifetime);
1044 }
1045 }
1046 fn on_generic_args_opt(&mut self, args: &Option<impl Borrow<GenericArgs>>) {
1047 if let Some(args) = args {
1048 self.on_generic_args(args.borrow());
1049 }
1050 }
1051
1052 fn on_exprs(&mut self, exprs: impl IntoIterator<Item: Borrow<ExprId>>) {
1053 exprs.into_iter().for_each(|expr| self.on_expr(*expr.borrow()));
1054 }
1055 fn on_pats(&mut self, pats: impl IntoIterator<Item: Borrow<PatId>>) {
1056 pats.into_iter().for_each(|pat| self.on_pat(*pat.borrow()));
1057 }
1058 fn on_types(&mut self, types: impl IntoIterator<Item: Borrow<TypeRefId>>) {
1059 types.into_iter().for_each(|ty| self.on_type(*ty.borrow()));
1060 }
1061 fn on_type_bounds(&mut self, bounds: impl IntoIterator<Item: Borrow<TypeBound>>) {
1062 bounds.into_iter().for_each(|bound| self.on_type_bound(bound.borrow()));
1063 }
1064}
1065impl<V: StoreVisitor> StoreVisitorExt for V {}
1066
1067impl Index<ExprId> for ExpressionStore {
1068 type Output = Expr;
1069
1070 #[inline]
1071 fn index(&self, expr: ExprId) -> &Expr {
1072 &self.assert_expr_only().exprs[expr]
1073 }
1074}
1075
1076impl Index<PatId> for ExpressionStore {
1077 type Output = Pat;
1078
1079 #[inline]
1080 fn index(&self, pat: PatId) -> &Pat {
1081 &self.assert_expr_only().pats[pat]
1082 }
1083}
1084
1085impl Index<LabelId> for ExpressionStore {
1086 type Output = Label;
1087
1088 #[inline]
1089 fn index(&self, label: LabelId) -> &Label {
1090 &self.assert_expr_only().labels[label]
1091 }
1092}
1093
1094impl Index<BindingId> for ExpressionStore {
1095 type Output = Binding;
1096
1097 #[inline]
1098 fn index(&self, b: BindingId) -> &Binding {
1099 &self.assert_expr_only().bindings[b]
1100 }
1101}
1102
1103impl Index<TypeRefId> for ExpressionStore {
1104 type Output = TypeRef;
1105
1106 #[inline]
1107 fn index(&self, b: TypeRefId) -> &TypeRef {
1108 &self.types[b]
1109 }
1110}
1111
1112impl Index<LifetimeRefId> for ExpressionStore {
1113 type Output = LifetimeRef;
1114
1115 #[inline]
1116 fn index(&self, b: LifetimeRefId) -> &LifetimeRef {
1117 &self.lifetimes[b]
1118 }
1119}
1120
1121impl Index<PathId> for ExpressionStore {
1122 type Output = Path;
1123
1124 #[inline]
1125 fn index(&self, index: PathId) -> &Self::Output {
1126 let TypeRef::Path(path) = &self[index.type_ref()] else {
1127 unreachable!("`PathId` always points to `TypeRef::Path`");
1128 };
1129 path
1130 }
1131}
1132
1133impl ExpressionStoreSourceMap {
1136 pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
1137 match id {
1138 ExprOrPatId::ExprId(id) => self.expr_syntax(id),
1139 ExprOrPatId::PatId(id) => self.pat_syntax(id),
1140 }
1141 }
1142
1143 #[inline]
1144 fn expr_or_synthetic(&self) -> Result<&ExpressionOnlySourceMap, SyntheticSyntax> {
1145 self.expr_only.as_deref().ok_or(SyntheticSyntax)
1146 }
1147
1148 #[inline]
1149 fn expr_only(&self) -> Option<&ExpressionOnlySourceMap> {
1150 self.expr_only.as_deref()
1151 }
1152
1153 #[inline]
1154 #[track_caller]
1155 fn assert_expr_only(&self) -> &ExpressionOnlySourceMap {
1156 self.expr_only.as_ref().expect("should have `ExpressionStoreSourceMap::expr_only`")
1157 }
1158
1159 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprOrPatSource, SyntheticSyntax> {
1160 self.expr_or_synthetic()?.expr_map_back.get(expr).cloned().ok_or(SyntheticSyntax)
1161 }
1162
1163 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprOrPatId> {
1164 let src = node.map(AstPtr::new);
1165 self.expr_only()?.expr_map.get(&src).cloned().map(ExprOrPatIdPacked::unpack)
1166 }
1167
1168 pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<MacroCallId> {
1169 let src = node.map(AstPtr::new);
1170 self.expr_only()?.expansions.get(&src).cloned()
1171 }
1172
1173 pub fn macro_calls(&self) -> impl Iterator<Item = (InFile<MacroCallPtr>, MacroCallId)> + '_ {
1174 self.expr_only().into_iter().flat_map(|it| it.expansions.iter().map(|(&a, &b)| (a, b)))
1175 }
1176
1177 pub fn pat_syntax(&self, pat: PatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
1178 self.expr_or_synthetic()?.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
1179 }
1180
1181 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<ExprOrPatId> {
1182 self.expr_only()?
1183 .pat_map
1184 .get(&node.map(AstPtr::new))
1185 .cloned()
1186 .map(ExprOrPatIdPacked::unpack)
1187 }
1188
1189 pub fn type_syntax(&self, id: TypeRefId) -> Result<TypeSource, SyntheticSyntax> {
1190 self.types_map_back.get(id).cloned().ok_or(SyntheticSyntax)
1191 }
1192
1193 pub fn node_type(&self, node: InFile<&ast::Type>) -> Option<TypeRefId> {
1194 self.types_map.get(&node.map(AstPtr::new)).cloned()
1195 }
1196
1197 pub fn label_syntax(&self, label: LabelId) -> LabelSource {
1198 self.assert_expr_only().label_map_back[label]
1199 }
1200
1201 pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] {
1202 self.assert_expr_only().binding_definitions.get(binding).map_or(&[], Deref::deref)
1203 }
1204
1205 pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
1206 let src = node.map(AstPtr::new).map(AstPtr::wrap_left);
1207 self.expr_only()?.label_map.get(&src).cloned()
1208 }
1209
1210 pub fn field_syntax(&self, expr: ExprId) -> FieldSource {
1211 self.assert_expr_only().field_map_back[&expr]
1212 }
1213
1214 pub fn pat_field_syntax(&self, pat: PatId) -> PatFieldSource {
1215 self.assert_expr_only().pat_field_map_back[&pat]
1216 }
1217
1218 pub fn macro_expansion_expr(&self, node: InFile<&ast::MacroExpr>) -> Option<ExprOrPatId> {
1219 let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::MacroExpr>).map(AstPtr::upcast);
1220 self.expr_only()?.expr_map.get(&src).copied().map(ExprOrPatIdPacked::unpack)
1221 }
1222
1223 pub fn expansions(&self) -> impl Iterator<Item = (&InFile<MacroCallPtr>, &MacroCallId)> {
1224 self.expr_only().into_iter().flat_map(|it| it.expansions.iter())
1225 }
1226
1227 pub fn expansion(&self, node: InFile<&ast::MacroCall>) -> Option<MacroCallId> {
1228 self.expr_only()?.expansions.get(&node.map(AstPtr::new)).copied()
1229 }
1230
1231 pub fn implicit_format_args(
1232 &self,
1233 node: InFile<&ast::FormatArgsExpr>,
1234 ) -> Option<(HygieneId, &[(syntax::TextRange, Name)])> {
1235 let expr_only = self.expr_only()?;
1236 let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
1237 let (hygiene, names) = expr_only
1238 .template_map
1239 .as_ref()?
1240 .format_args_to_captures
1241 .get(&expr_only.expr_map.get(&src)?.as_expr()?)?;
1242 Some((*hygiene, &**names))
1243 }
1244
1245 pub fn format_args_implicit_capture(
1246 &self,
1247 capture_expr: ExprId,
1248 ) -> Option<InFile<(ExprPtr, TextRange)>> {
1249 self.expr_only()?
1250 .template_map
1251 .as_ref()?
1252 .implicit_capture_to_source
1253 .get(&capture_expr)
1254 .copied()
1255 }
1256
1257 pub fn asm_template_args(
1258 &self,
1259 node: InFile<&ast::AsmExpr>,
1260 ) -> Option<(ExprId, &[Vec<(syntax::TextRange, usize)>])> {
1261 let expr_only = self.expr_only()?;
1262 let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
1263 let expr = expr_only.expr_map.get(&src)?.as_expr()?;
1264 Some(expr).zip(
1265 expr_only.template_map.as_ref()?.asm_to_captures.get(&expr).map(std::ops::Deref::deref),
1266 )
1267 }
1268
1269 pub fn diagnostics(&self) -> &[ExpressionStoreDiagnostics] {
1271 self.expr_only().map(|it| &*it.diagnostics).unwrap_or_default()
1272 }
1273}