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