]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
Auto merge of #107843 - bjorn3:sync_cg_clif-2023-02-09, r=bjorn3
[rust.git] / src / tools / rust-analyzer / crates / hir-def / src / body / lower.rs
1 //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2 //! representation.
3
4 use std::{mem, sync::Arc};
5
6 use either::Either;
7 use hir_expand::{
8     ast_id_map::AstIdMap,
9     hygiene::Hygiene,
10     name::{name, AsName, Name},
11     AstId, ExpandError, HirFileId, InFile,
12 };
13 use la_arena::Arena;
14 use once_cell::unsync::OnceCell;
15 use profile::Count;
16 use rustc_hash::FxHashMap;
17 use syntax::{
18     ast::{
19         self, ArrayExprKind, AstChildren, HasArgList, HasLoopBody, HasName, LiteralKind,
20         SlicePatComponents,
21     },
22     AstNode, AstPtr, SyntaxNodePtr,
23 };
24
25 use crate::{
26     adt::StructKind,
27     body::{Body, BodySourceMap, Expander, ExprPtr, LabelPtr, LabelSource, PatPtr},
28     body::{BodyDiagnostic, ExprSource, PatSource},
29     builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
30     db::DefDatabase,
31     expr::{
32         dummy_expr_id, Array, BindingAnnotation, ClosureKind, Expr, ExprId, FloatTypeWrapper,
33         Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
34         Statement,
35     },
36     intern::Interned,
37     item_scope::BuiltinShadowMode,
38     path::{GenericArgs, Path},
39     type_ref::{Mutability, Rawness, TypeRef},
40     AdtId, BlockLoc, ModuleDefId, UnresolvedMacro,
41 };
42
43 pub struct LowerCtx<'a> {
44     pub db: &'a dyn DefDatabase,
45     hygiene: Hygiene,
46     ast_id_map: Option<(HirFileId, OnceCell<Arc<AstIdMap>>)>,
47 }
48
49 impl<'a> LowerCtx<'a> {
50     pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
51         LowerCtx {
52             db,
53             hygiene: Hygiene::new(db.upcast(), file_id),
54             ast_id_map: Some((file_id, OnceCell::new())),
55         }
56     }
57
58     pub fn with_hygiene(db: &'a dyn DefDatabase, hygiene: &Hygiene) -> Self {
59         LowerCtx { db, hygiene: hygiene.clone(), ast_id_map: None }
60     }
61
62     pub(crate) fn hygiene(&self) -> &Hygiene {
63         &self.hygiene
64     }
65
66     pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
67         Path::from_src(ast, self)
68     }
69
70     pub(crate) fn ast_id<N: AstNode>(&self, db: &dyn DefDatabase, item: &N) -> Option<AstId<N>> {
71         let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
72         let ast_id_map = ast_id_map.get_or_init(|| db.ast_id_map(file_id));
73         Some(InFile::new(file_id, ast_id_map.ast_id(item)))
74     }
75 }
76
77 pub(super) fn lower(
78     db: &dyn DefDatabase,
79     expander: Expander,
80     params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
81     body: Option<ast::Expr>,
82 ) -> (Body, BodySourceMap) {
83     ExprCollector {
84         db,
85         source_map: BodySourceMap::default(),
86         ast_id_map: db.ast_id_map(expander.current_file_id),
87         body: Body {
88             exprs: Arena::default(),
89             pats: Arena::default(),
90             labels: Arena::default(),
91             params: Vec::new(),
92             body_expr: dummy_expr_id(),
93             block_scopes: Vec::new(),
94             _c: Count::new(),
95             or_pats: Default::default(),
96         },
97         expander,
98         name_to_pat_grouping: Default::default(),
99         is_lowering_inside_or_pat: false,
100         is_lowering_assignee_expr: false,
101         is_lowering_generator: false,
102     }
103     .collect(params, body)
104 }
105
106 struct ExprCollector<'a> {
107     db: &'a dyn DefDatabase,
108     expander: Expander,
109     ast_id_map: Arc<AstIdMap>,
110     body: Body,
111     source_map: BodySourceMap,
112     // a poor-mans union-find?
113     name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
114     is_lowering_inside_or_pat: bool,
115     is_lowering_assignee_expr: bool,
116     is_lowering_generator: bool,
117 }
118
119 impl ExprCollector<'_> {
120     fn collect(
121         mut self,
122         param_list: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
123         body: Option<ast::Expr>,
124     ) -> (Body, BodySourceMap) {
125         if let Some((param_list, mut attr_enabled)) = param_list {
126             if let Some(self_param) =
127                 param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
128             {
129                 let ptr = AstPtr::new(&self_param);
130                 let param_pat = self.alloc_pat(
131                     Pat::Bind {
132                         name: name![self],
133                         mode: BindingAnnotation::new(
134                             self_param.mut_token().is_some() && self_param.amp_token().is_none(),
135                             false,
136                         ),
137                         subpat: None,
138                     },
139                     Either::Right(ptr),
140                 );
141                 self.body.params.push(param_pat);
142             }
143
144             for pat in param_list
145                 .params()
146                 .zip(attr_enabled)
147                 .filter_map(|(param, enabled)| param.pat().filter(|_| enabled))
148             {
149                 let param_pat = self.collect_pat(pat);
150                 self.body.params.push(param_pat);
151             }
152         };
153
154         self.body.body_expr = self.collect_expr_opt(body);
155         (self.body, self.source_map)
156     }
157
158     fn ctx(&self) -> LowerCtx<'_> {
159         LowerCtx::new(self.db, self.expander.current_file_id)
160     }
161
162     fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
163         let src = self.expander.to_source(ptr);
164         let id = self.make_expr(expr, src.clone());
165         self.source_map.expr_map.insert(src, id);
166         id
167     }
168     // desugared exprs don't have ptr, that's wrong and should be fixed
169     // somehow.
170     fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
171         self.body.exprs.alloc(expr)
172     }
173     fn missing_expr(&mut self) -> ExprId {
174         self.alloc_expr_desugared(Expr::Missing)
175     }
176     fn make_expr(&mut self, expr: Expr, src: ExprSource) -> ExprId {
177         let id = self.body.exprs.alloc(expr);
178         self.source_map.expr_map_back.insert(id, src);
179         id
180     }
181
182     fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
183         let src = self.expander.to_source(ptr);
184         let id = self.make_pat(pat, src.clone());
185         self.source_map.pat_map.insert(src, id);
186         id
187     }
188     fn missing_pat(&mut self) -> PatId {
189         self.body.pats.alloc(Pat::Missing)
190     }
191     fn make_pat(&mut self, pat: Pat, src: PatSource) -> PatId {
192         let id = self.body.pats.alloc(pat);
193         self.source_map.pat_map_back.insert(id, src);
194         id
195     }
196
197     fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
198         let src = self.expander.to_source(ptr);
199         let id = self.make_label(label, src.clone());
200         self.source_map.label_map.insert(src, id);
201         id
202     }
203     fn make_label(&mut self, label: Label, src: LabelSource) -> LabelId {
204         let id = self.body.labels.alloc(label);
205         self.source_map.label_map_back.insert(id, src);
206         id
207     }
208
209     fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
210         self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
211     }
212
213     /// Returns `None` if and only if the expression is `#[cfg]`d out.
214     fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
215         let syntax_ptr = AstPtr::new(&expr);
216         self.check_cfg(&expr)?;
217
218         Some(match expr {
219             ast::Expr::IfExpr(e) => {
220                 let then_branch = self.collect_block_opt(e.then_branch());
221
222                 let else_branch = e.else_branch().map(|b| match b {
223                     ast::ElseBranch::Block(it) => self.collect_block(it),
224                     ast::ElseBranch::IfExpr(elif) => {
225                         let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
226                         self.collect_expr(expr)
227                     }
228                 });
229
230                 let condition = self.collect_expr_opt(e.condition());
231
232                 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
233             }
234             ast::Expr::LetExpr(e) => {
235                 let pat = self.collect_pat_opt(e.pat());
236                 let expr = self.collect_expr_opt(e.expr());
237                 self.alloc_expr(Expr::Let { pat, expr }, syntax_ptr)
238             }
239             ast::Expr::BlockExpr(e) => match e.modifier() {
240                 Some(ast::BlockModifier::Try(_)) => {
241                     let body = self.collect_block(e);
242                     self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
243                 }
244                 Some(ast::BlockModifier::Unsafe(_)) => {
245                     let body = self.collect_block(e);
246                     self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
247                 }
248                 // FIXME: we need to record these effects somewhere...
249                 Some(ast::BlockModifier::Label(label)) => {
250                     let label = self.collect_label(label);
251                     let res = self.collect_block(e);
252                     match &mut self.body.exprs[res] {
253                         Expr::Block { label: block_label, .. } => {
254                             *block_label = Some(label);
255                         }
256                         _ => unreachable!(),
257                     }
258                     res
259                 }
260                 Some(ast::BlockModifier::Async(_)) => {
261                     let body = self.collect_block(e);
262                     self.alloc_expr(Expr::Async { body }, syntax_ptr)
263                 }
264                 Some(ast::BlockModifier::Const(_)) => {
265                     let body = self.collect_block(e);
266                     self.alloc_expr(Expr::Const { body }, syntax_ptr)
267                 }
268                 None => self.collect_block(e),
269             },
270             ast::Expr::LoopExpr(e) => {
271                 let label = e.label().map(|label| self.collect_label(label));
272                 let body = self.collect_block_opt(e.loop_body());
273                 self.alloc_expr(Expr::Loop { body, label }, syntax_ptr)
274             }
275             ast::Expr::WhileExpr(e) => {
276                 let label = e.label().map(|label| self.collect_label(label));
277                 let body = self.collect_block_opt(e.loop_body());
278
279                 let condition = self.collect_expr_opt(e.condition());
280
281                 self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr)
282             }
283             ast::Expr::ForExpr(e) => {
284                 let label = e.label().map(|label| self.collect_label(label));
285                 let iterable = self.collect_expr_opt(e.iterable());
286                 let pat = self.collect_pat_opt(e.pat());
287                 let body = self.collect_block_opt(e.loop_body());
288                 self.alloc_expr(Expr::For { iterable, pat, body, label }, syntax_ptr)
289             }
290             ast::Expr::CallExpr(e) => {
291                 let callee = self.collect_expr_opt(e.expr());
292                 let args = if let Some(arg_list) = e.arg_list() {
293                     arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
294                 } else {
295                     Box::default()
296                 };
297                 self.alloc_expr(
298                     Expr::Call { callee, args, is_assignee_expr: self.is_lowering_assignee_expr },
299                     syntax_ptr,
300                 )
301             }
302             ast::Expr::MethodCallExpr(e) => {
303                 let receiver = self.collect_expr_opt(e.receiver());
304                 let args = if let Some(arg_list) = e.arg_list() {
305                     arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
306                 } else {
307                     Box::default()
308                 };
309                 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
310                 let generic_args = e
311                     .generic_arg_list()
312                     .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
313                     .map(Box::new);
314                 self.alloc_expr(
315                     Expr::MethodCall { receiver, method_name, args, generic_args },
316                     syntax_ptr,
317                 )
318             }
319             ast::Expr::MatchExpr(e) => {
320                 let expr = self.collect_expr_opt(e.expr());
321                 let arms = if let Some(match_arm_list) = e.match_arm_list() {
322                     match_arm_list
323                         .arms()
324                         .filter_map(|arm| {
325                             self.check_cfg(&arm).map(|()| MatchArm {
326                                 pat: self.collect_pat_opt(arm.pat()),
327                                 expr: self.collect_expr_opt(arm.expr()),
328                                 guard: arm
329                                     .guard()
330                                     .map(|guard| self.collect_expr_opt(guard.condition())),
331                             })
332                         })
333                         .collect()
334                 } else {
335                     Box::default()
336                 };
337                 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
338             }
339             ast::Expr::PathExpr(e) => {
340                 let path = e
341                     .path()
342                     .and_then(|path| self.expander.parse_path(self.db, path))
343                     .map(Expr::Path)
344                     .unwrap_or(Expr::Missing);
345                 self.alloc_expr(path, syntax_ptr)
346             }
347             ast::Expr::ContinueExpr(e) => self.alloc_expr(
348                 Expr::Continue { label: e.lifetime().map(|l| Name::new_lifetime(&l)) },
349                 syntax_ptr,
350             ),
351             ast::Expr::BreakExpr(e) => {
352                 let expr = e.expr().map(|e| self.collect_expr(e));
353                 self.alloc_expr(
354                     Expr::Break { expr, label: e.lifetime().map(|l| Name::new_lifetime(&l)) },
355                     syntax_ptr,
356                 )
357             }
358             ast::Expr::ParenExpr(e) => {
359                 let inner = self.collect_expr_opt(e.expr());
360                 // make the paren expr point to the inner expression as well
361                 let src = self.expander.to_source(syntax_ptr);
362                 self.source_map.expr_map.insert(src, inner);
363                 inner
364             }
365             ast::Expr::ReturnExpr(e) => {
366                 let expr = e.expr().map(|e| self.collect_expr(e));
367                 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
368             }
369             ast::Expr::YieldExpr(e) => {
370                 self.is_lowering_generator = true;
371                 let expr = e.expr().map(|e| self.collect_expr(e));
372                 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
373             }
374             ast::Expr::YeetExpr(e) => {
375                 let expr = e.expr().map(|e| self.collect_expr(e));
376                 self.alloc_expr(Expr::Yeet { expr }, syntax_ptr)
377             }
378             ast::Expr::RecordExpr(e) => {
379                 let path =
380                     e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
381                 let is_assignee_expr = self.is_lowering_assignee_expr;
382                 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
383                     let fields = nfl
384                         .fields()
385                         .filter_map(|field| {
386                             self.check_cfg(&field)?;
387
388                             let name = field.field_name()?.as_name();
389
390                             let expr = match field.expr() {
391                                 Some(e) => self.collect_expr(e),
392                                 None => self.missing_expr(),
393                             };
394                             let src = self.expander.to_source(AstPtr::new(&field));
395                             self.source_map.field_map.insert(src.clone(), expr);
396                             self.source_map.field_map_back.insert(expr, src);
397                             Some(RecordLitField { name, expr })
398                         })
399                         .collect();
400                     let spread = nfl.spread().map(|s| self.collect_expr(s));
401                     let ellipsis = nfl.dotdot_token().is_some();
402                     Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr }
403                 } else {
404                     Expr::RecordLit {
405                         path,
406                         fields: Box::default(),
407                         spread: None,
408                         ellipsis: false,
409                         is_assignee_expr,
410                     }
411                 };
412
413                 self.alloc_expr(record_lit, syntax_ptr)
414             }
415             ast::Expr::FieldExpr(e) => {
416                 let expr = self.collect_expr_opt(e.expr());
417                 let name = match e.field_access() {
418                     Some(kind) => kind.as_name(),
419                     _ => Name::missing(),
420                 };
421                 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
422             }
423             ast::Expr::AwaitExpr(e) => {
424                 let expr = self.collect_expr_opt(e.expr());
425                 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
426             }
427             ast::Expr::TryExpr(e) => {
428                 let expr = self.collect_expr_opt(e.expr());
429                 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
430             }
431             ast::Expr::CastExpr(e) => {
432                 let expr = self.collect_expr_opt(e.expr());
433                 let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
434                 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
435             }
436             ast::Expr::RefExpr(e) => {
437                 let expr = self.collect_expr_opt(e.expr());
438                 let raw_tok = e.raw_token().is_some();
439                 let mutability = if raw_tok {
440                     if e.mut_token().is_some() {
441                         Mutability::Mut
442                     } else if e.const_token().is_some() {
443                         Mutability::Shared
444                     } else {
445                         unreachable!("parser only remaps to raw_token() if matching mutability token follows")
446                     }
447                 } else {
448                     Mutability::from_mutable(e.mut_token().is_some())
449                 };
450                 let rawness = Rawness::from_raw(raw_tok);
451                 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
452             }
453             ast::Expr::PrefixExpr(e) => {
454                 let expr = self.collect_expr_opt(e.expr());
455                 match e.op_kind() {
456                     Some(op) => self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr),
457                     None => self.alloc_expr(Expr::Missing, syntax_ptr),
458                 }
459             }
460             ast::Expr::ClosureExpr(e) => {
461                 let mut args = Vec::new();
462                 let mut arg_types = Vec::new();
463                 if let Some(pl) = e.param_list() {
464                     for param in pl.params() {
465                         let pat = self.collect_pat_opt(param.pat());
466                         let type_ref =
467                             param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
468                         args.push(pat);
469                         arg_types.push(type_ref);
470                     }
471                 }
472                 let ret_type = e
473                     .ret_type()
474                     .and_then(|r| r.ty())
475                     .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
476
477                 let prev_is_lowering_generator = self.is_lowering_generator;
478                 self.is_lowering_generator = false;
479
480                 let body = self.collect_expr_opt(e.body());
481
482                 let closure_kind = if self.is_lowering_generator {
483                     let movability = if e.static_token().is_some() {
484                         Movability::Static
485                     } else {
486                         Movability::Movable
487                     };
488                     ClosureKind::Generator(movability)
489                 } else {
490                     ClosureKind::Closure
491                 };
492                 self.is_lowering_generator = prev_is_lowering_generator;
493
494                 self.alloc_expr(
495                     Expr::Closure {
496                         args: args.into(),
497                         arg_types: arg_types.into(),
498                         ret_type,
499                         body,
500                         closure_kind,
501                     },
502                     syntax_ptr,
503                 )
504             }
505             ast::Expr::BinExpr(e) => {
506                 let op = e.op_kind();
507                 if let Some(ast::BinaryOp::Assignment { op: None }) = op {
508                     self.is_lowering_assignee_expr = true;
509                 }
510                 let lhs = self.collect_expr_opt(e.lhs());
511                 self.is_lowering_assignee_expr = false;
512                 let rhs = self.collect_expr_opt(e.rhs());
513                 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
514             }
515             ast::Expr::TupleExpr(e) => {
516                 let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
517                 self.alloc_expr(
518                     Expr::Tuple { exprs, is_assignee_expr: self.is_lowering_assignee_expr },
519                     syntax_ptr,
520                 )
521             }
522             ast::Expr::BoxExpr(e) => {
523                 let expr = self.collect_expr_opt(e.expr());
524                 self.alloc_expr(Expr::Box { expr }, syntax_ptr)
525             }
526
527             ast::Expr::ArrayExpr(e) => {
528                 let kind = e.kind();
529
530                 match kind {
531                     ArrayExprKind::ElementList(e) => {
532                         let elements = e.map(|expr| self.collect_expr(expr)).collect();
533                         self.alloc_expr(
534                             Expr::Array(Array::ElementList {
535                                 elements,
536                                 is_assignee_expr: self.is_lowering_assignee_expr,
537                             }),
538                             syntax_ptr,
539                         )
540                     }
541                     ArrayExprKind::Repeat { initializer, repeat } => {
542                         let initializer = self.collect_expr_opt(initializer);
543                         let repeat = self.collect_expr_opt(repeat);
544                         self.alloc_expr(
545                             Expr::Array(Array::Repeat { initializer, repeat }),
546                             syntax_ptr,
547                         )
548                     }
549                 }
550             }
551
552             ast::Expr::Literal(e) => self.alloc_expr(Expr::Literal(e.kind().into()), syntax_ptr),
553             ast::Expr::IndexExpr(e) => {
554                 let base = self.collect_expr_opt(e.base());
555                 let index = self.collect_expr_opt(e.index());
556                 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
557             }
558             ast::Expr::RangeExpr(e) => {
559                 let lhs = e.start().map(|lhs| self.collect_expr(lhs));
560                 let rhs = e.end().map(|rhs| self.collect_expr(rhs));
561                 match e.op_kind() {
562                     Some(range_type) => {
563                         self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr)
564                     }
565                     None => self.alloc_expr(Expr::Missing, syntax_ptr),
566                 }
567             }
568             ast::Expr::MacroExpr(e) => {
569                 let e = e.macro_call()?;
570                 let macro_ptr = AstPtr::new(&e);
571                 let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
572                     expansion.map(|it| this.collect_expr(it))
573                 });
574                 match id {
575                     Some(id) => {
576                         // Make the macro-call point to its expanded expression so we can query
577                         // semantics on syntax pointers to the macro
578                         let src = self.expander.to_source(syntax_ptr);
579                         self.source_map.expr_map.insert(src, id);
580                         id
581                     }
582                     None => self.alloc_expr(Expr::Missing, syntax_ptr),
583                 }
584             }
585             ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
586         })
587     }
588
589     fn collect_macro_call<F, T, U>(
590         &mut self,
591         mcall: ast::MacroCall,
592         syntax_ptr: AstPtr<ast::MacroCall>,
593         record_diagnostics: bool,
594         collector: F,
595     ) -> U
596     where
597         F: FnOnce(&mut Self, Option<T>) -> U,
598         T: ast::AstNode,
599     {
600         // File containing the macro call. Expansion errors will be attached here.
601         let outer_file = self.expander.current_file_id;
602
603         let macro_call_ptr = self.expander.to_source(AstPtr::new(&mcall));
604         let res = self.expander.enter_expand(self.db, mcall);
605
606         let res = match res {
607             Ok(res) => res,
608             Err(UnresolvedMacro { path }) => {
609                 if record_diagnostics {
610                     self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall {
611                         node: InFile::new(outer_file, syntax_ptr),
612                         path,
613                     });
614                 }
615                 return collector(self, None);
616             }
617         };
618
619         if record_diagnostics {
620             match &res.err {
621                 Some(ExpandError::UnresolvedProcMacro(krate)) => {
622                     self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro {
623                         node: InFile::new(outer_file, syntax_ptr),
624                         krate: *krate,
625                     });
626                 }
627                 Some(err) => {
628                     self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
629                         node: InFile::new(outer_file, syntax_ptr),
630                         message: err.to_string(),
631                     });
632                 }
633                 None => {}
634             }
635         }
636
637         match res.value {
638             Some((mark, expansion)) => {
639                 self.source_map.expansions.insert(macro_call_ptr, self.expander.current_file_id);
640                 let prev_ast_id_map = mem::replace(
641                     &mut self.ast_id_map,
642                     self.db.ast_id_map(self.expander.current_file_id),
643                 );
644
645                 let id = collector(self, Some(expansion));
646                 self.ast_id_map = prev_ast_id_map;
647                 self.expander.exit(self.db, mark);
648                 id
649             }
650             None => collector(self, None),
651         }
652     }
653
654     fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
655         match expr {
656             Some(expr) => self.collect_expr(expr),
657             None => self.missing_expr(),
658         }
659     }
660
661     fn collect_macro_as_stmt(
662         &mut self,
663         statements: &mut Vec<Statement>,
664         mac: ast::MacroExpr,
665     ) -> Option<ExprId> {
666         let mac_call = mac.macro_call()?;
667         let syntax_ptr = AstPtr::new(&ast::Expr::from(mac));
668         let macro_ptr = AstPtr::new(&mac_call);
669         let expansion = self.collect_macro_call(
670             mac_call,
671             macro_ptr,
672             false,
673             |this, expansion: Option<ast::MacroStmts>| match expansion {
674                 Some(expansion) => {
675                     expansion.statements().for_each(|stmt| this.collect_stmt(statements, stmt));
676                     expansion.expr().and_then(|expr| match expr {
677                         ast::Expr::MacroExpr(mac) => this.collect_macro_as_stmt(statements, mac),
678                         expr => Some(this.collect_expr(expr)),
679                     })
680                 }
681                 None => None,
682             },
683         );
684         match expansion {
685             Some(tail) => {
686                 // Make the macro-call point to its expanded expression so we can query
687                 // semantics on syntax pointers to the macro
688                 let src = self.expander.to_source(syntax_ptr);
689                 self.source_map.expr_map.insert(src, tail);
690                 Some(tail)
691             }
692             None => None,
693         }
694     }
695
696     fn collect_stmt(&mut self, statements: &mut Vec<Statement>, s: ast::Stmt) {
697         match s {
698             ast::Stmt::LetStmt(stmt) => {
699                 if self.check_cfg(&stmt).is_none() {
700                     return;
701                 }
702                 let pat = self.collect_pat_opt(stmt.pat());
703                 let type_ref =
704                     stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
705                 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
706                 let else_branch = stmt
707                     .let_else()
708                     .and_then(|let_else| let_else.block_expr())
709                     .map(|block| self.collect_block(block));
710                 statements.push(Statement::Let { pat, type_ref, initializer, else_branch });
711             }
712             ast::Stmt::ExprStmt(stmt) => {
713                 let expr = stmt.expr();
714                 match &expr {
715                     Some(expr) if self.check_cfg(expr).is_none() => return,
716                     _ => (),
717                 }
718                 let has_semi = stmt.semicolon_token().is_some();
719                 // Note that macro could be expanded to multiple statements
720                 if let Some(ast::Expr::MacroExpr(mac)) = expr {
721                     if let Some(expr) = self.collect_macro_as_stmt(statements, mac) {
722                         statements.push(Statement::Expr { expr, has_semi })
723                     }
724                 } else {
725                     let expr = self.collect_expr_opt(expr);
726                     statements.push(Statement::Expr { expr, has_semi });
727                 }
728             }
729             ast::Stmt::Item(_item) => (),
730         }
731     }
732
733     fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
734         let file_local_id = self.ast_id_map.ast_id(&block);
735         let ast_id = AstId::new(self.expander.current_file_id, file_local_id);
736         let block_loc =
737             BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
738         let block_id = self.db.intern_block(block_loc);
739
740         let (module, def_map) = match self.db.block_def_map(block_id) {
741             Some(def_map) => {
742                 self.body.block_scopes.push(block_id);
743                 (def_map.root(), def_map)
744             }
745             None => (self.expander.module, self.expander.def_map.clone()),
746         };
747         let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
748         let prev_local_module = mem::replace(&mut self.expander.module, module);
749
750         let mut statements = Vec::new();
751         block.statements().for_each(|s| self.collect_stmt(&mut statements, s));
752         let tail = block.tail_expr().and_then(|e| match e {
753             ast::Expr::MacroExpr(mac) => self.collect_macro_as_stmt(&mut statements, mac),
754             expr => self.maybe_collect_expr(expr),
755         });
756         let tail = tail.or_else(|| {
757             let stmt = statements.pop()?;
758             if let Statement::Expr { expr, has_semi: false } = stmt {
759                 return Some(expr);
760             }
761             statements.push(stmt);
762             None
763         });
764
765         let syntax_node_ptr = AstPtr::new(&block.into());
766         let expr_id = self.alloc_expr(
767             Expr::Block {
768                 id: block_id,
769                 statements: statements.into_boxed_slice(),
770                 tail,
771                 label: None,
772             },
773             syntax_node_ptr,
774         );
775
776         self.expander.def_map = prev_def_map;
777         self.expander.module = prev_local_module;
778         expr_id
779     }
780
781     fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
782         match expr {
783             Some(block) => self.collect_block(block),
784             None => self.missing_expr(),
785         }
786     }
787
788     fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
789         let label = Label {
790             name: ast_label.lifetime().as_ref().map_or_else(Name::missing, Name::new_lifetime),
791         };
792         self.alloc_label(label, AstPtr::new(&ast_label))
793     }
794
795     fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
796         let pat_id = self.collect_pat_(pat);
797         for (_, pats) in self.name_to_pat_grouping.drain() {
798             let pats = Arc::<[_]>::from(pats);
799             self.body.or_pats.extend(pats.iter().map(|&pat| (pat, pats.clone())));
800         }
801         self.is_lowering_inside_or_pat = false;
802         pat_id
803     }
804
805     fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
806         match pat {
807             Some(pat) => self.collect_pat(pat),
808             None => self.missing_pat(),
809         }
810     }
811
812     fn collect_pat_(&mut self, pat: ast::Pat) -> PatId {
813         let pattern = match &pat {
814             ast::Pat::IdentPat(bp) => {
815                 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
816
817                 let key = self.is_lowering_inside_or_pat.then(|| name.clone());
818                 let annotation =
819                     BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
820                 let subpat = bp.pat().map(|subpat| self.collect_pat_(subpat));
821                 let pattern = if annotation == BindingAnnotation::Unannotated && subpat.is_none() {
822                     // This could also be a single-segment path pattern. To
823                     // decide that, we need to try resolving the name.
824                     let (resolved, _) = self.expander.def_map.resolve_path(
825                         self.db,
826                         self.expander.module,
827                         &name.clone().into(),
828                         BuiltinShadowMode::Other,
829                     );
830                     match resolved.take_values() {
831                         Some(ModuleDefId::ConstId(_)) => Pat::Path(name.into()),
832                         Some(ModuleDefId::EnumVariantId(_)) => {
833                             // this is only really valid for unit variants, but
834                             // shadowing other enum variants with a pattern is
835                             // an error anyway
836                             Pat::Path(name.into())
837                         }
838                         Some(ModuleDefId::AdtId(AdtId::StructId(s)))
839                             if self.db.struct_data(s).variant_data.kind() != StructKind::Record =>
840                         {
841                             // Funnily enough, record structs *can* be shadowed
842                             // by pattern bindings (but unit or tuple structs
843                             // can't).
844                             Pat::Path(name.into())
845                         }
846                         // shadowing statics is an error as well, so we just ignore that case here
847                         _ => Pat::Bind { name, mode: annotation, subpat },
848                     }
849                 } else {
850                     Pat::Bind { name, mode: annotation, subpat }
851                 };
852
853                 let ptr = AstPtr::new(&pat);
854                 let pat = self.alloc_pat(pattern, Either::Left(ptr));
855                 if let Some(key) = key {
856                     self.name_to_pat_grouping.entry(key).or_default().push(pat);
857                 }
858                 return pat;
859             }
860             ast::Pat::TupleStructPat(p) => {
861                 let path =
862                     p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
863                 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
864                 Pat::TupleStruct { path, args, ellipsis }
865             }
866             ast::Pat::RefPat(p) => {
867                 let pat = self.collect_pat_opt(p.pat());
868                 let mutability = Mutability::from_mutable(p.mut_token().is_some());
869                 Pat::Ref { pat, mutability }
870             }
871             ast::Pat::PathPat(p) => {
872                 let path =
873                     p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
874                 path.map(Pat::Path).unwrap_or(Pat::Missing)
875             }
876             ast::Pat::OrPat(p) => {
877                 self.is_lowering_inside_or_pat = true;
878                 let pats = p.pats().map(|p| self.collect_pat_(p)).collect();
879                 Pat::Or(pats)
880             }
881             ast::Pat::ParenPat(p) => return self.collect_pat_opt_(p.pat()),
882             ast::Pat::TuplePat(p) => {
883                 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
884                 Pat::Tuple { args, ellipsis }
885             }
886             ast::Pat::WildcardPat(_) => Pat::Wild,
887             ast::Pat::RecordPat(p) => {
888                 let path =
889                     p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
890                 let args = p
891                     .record_pat_field_list()
892                     .expect("every struct should have a field list")
893                     .fields()
894                     .filter_map(|f| {
895                         let ast_pat = f.pat()?;
896                         let pat = self.collect_pat_(ast_pat);
897                         let name = f.field_name()?.as_name();
898                         Some(RecordFieldPat { name, pat })
899                     })
900                     .collect();
901
902                 let ellipsis = p
903                     .record_pat_field_list()
904                     .expect("every struct should have a field list")
905                     .rest_pat()
906                     .is_some();
907
908                 Pat::Record { path, args, ellipsis }
909             }
910             ast::Pat::SlicePat(p) => {
911                 let SlicePatComponents { prefix, slice, suffix } = p.components();
912
913                 // FIXME properly handle `RestPat`
914                 Pat::Slice {
915                     prefix: prefix.into_iter().map(|p| self.collect_pat_(p)).collect(),
916                     slice: slice.map(|p| self.collect_pat_(p)),
917                     suffix: suffix.into_iter().map(|p| self.collect_pat_(p)).collect(),
918                 }
919             }
920             ast::Pat::LiteralPat(lit) => {
921                 if let Some(ast_lit) = lit.literal() {
922                     let expr = Expr::Literal(ast_lit.kind().into());
923                     let expr_ptr = AstPtr::new(&ast::Expr::Literal(ast_lit));
924                     let expr_id = self.alloc_expr(expr, expr_ptr);
925                     Pat::Lit(expr_id)
926                 } else {
927                     Pat::Missing
928                 }
929             }
930             ast::Pat::RestPat(_) => {
931                 // `RestPat` requires special handling and should not be mapped
932                 // to a Pat. Here we are using `Pat::Missing` as a fallback for
933                 // when `RestPat` is mapped to `Pat`, which can easily happen
934                 // when the source code being analyzed has a malformed pattern
935                 // which includes `..` in a place where it isn't valid.
936
937                 Pat::Missing
938             }
939             ast::Pat::BoxPat(boxpat) => {
940                 let inner = self.collect_pat_opt_(boxpat.pat());
941                 Pat::Box { inner }
942             }
943             ast::Pat::ConstBlockPat(const_block_pat) => {
944                 if let Some(expr) = const_block_pat.block_expr() {
945                     let expr_id = self.collect_block(expr);
946                     Pat::ConstBlock(expr_id)
947                 } else {
948                     Pat::Missing
949                 }
950             }
951             ast::Pat::MacroPat(mac) => match mac.macro_call() {
952                 Some(call) => {
953                     let macro_ptr = AstPtr::new(&call);
954                     let src = self.expander.to_source(Either::Left(AstPtr::new(&pat)));
955                     let pat =
956                         self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
957                             this.collect_pat_opt_(expanded_pat)
958                         });
959                     self.source_map.pat_map.insert(src, pat);
960                     return pat;
961                 }
962                 None => Pat::Missing,
963             },
964             // FIXME: implement
965             ast::Pat::RangePat(_) => Pat::Missing,
966         };
967         let ptr = AstPtr::new(&pat);
968         self.alloc_pat(pattern, Either::Left(ptr))
969     }
970
971     fn collect_pat_opt_(&mut self, pat: Option<ast::Pat>) -> PatId {
972         match pat {
973             Some(pat) => self.collect_pat_(pat),
974             None => self.missing_pat(),
975         }
976     }
977
978     fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Box<[PatId]>, Option<usize>) {
979         // Find the location of the `..`, if there is one. Note that we do not
980         // consider the possibility of there being multiple `..` here.
981         let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
982         // We want to skip the `..` pattern here, since we account for it above.
983         let args = args
984             .filter(|p| !matches!(p, ast::Pat::RestPat(_)))
985             .map(|p| self.collect_pat_(p))
986             .collect();
987
988         (args, ellipsis)
989     }
990
991     /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
992     /// not.
993     fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> Option<()> {
994         match self.expander.parse_attrs(self.db, owner).cfg() {
995             Some(cfg) => {
996                 if self.expander.cfg_options().check(&cfg) != Some(false) {
997                     return Some(());
998                 }
999
1000                 self.source_map.diagnostics.push(BodyDiagnostic::InactiveCode {
1001                     node: InFile::new(
1002                         self.expander.current_file_id,
1003                         SyntaxNodePtr::new(owner.syntax()),
1004                     ),
1005                     cfg,
1006                     opts: self.expander.cfg_options().clone(),
1007                 });
1008
1009                 None
1010             }
1011             None => Some(()),
1012         }
1013     }
1014 }
1015
1016 impl From<ast::LiteralKind> for Literal {
1017     fn from(ast_lit_kind: ast::LiteralKind) -> Self {
1018         match ast_lit_kind {
1019             // FIXME: these should have actual values filled in, but unsure on perf impact
1020             LiteralKind::IntNumber(lit) => {
1021                 if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
1022                     Literal::Float(
1023                         FloatTypeWrapper::new(lit.float_value().unwrap_or(Default::default())),
1024                         builtin,
1025                     )
1026                 } else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinInt::from_suffix) {
1027                     Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
1028                 } else {
1029                     let builtin = lit.suffix().and_then(BuiltinUint::from_suffix);
1030                     Literal::Uint(lit.value().unwrap_or(0), builtin)
1031                 }
1032             }
1033             LiteralKind::FloatNumber(lit) => {
1034                 let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
1035                 Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
1036             }
1037             LiteralKind::ByteString(bs) => {
1038                 let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
1039                 Literal::ByteString(text)
1040             }
1041             LiteralKind::String(s) => {
1042                 let text = s.value().map(Box::from).unwrap_or_else(Default::default);
1043                 Literal::String(text)
1044             }
1045             LiteralKind::Byte(b) => {
1046                 Literal::Uint(b.value().unwrap_or_default() as u128, Some(BuiltinUint::U8))
1047             }
1048             LiteralKind::Char(c) => Literal::Char(c.value().unwrap_or_default()),
1049             LiteralKind::Bool(val) => Literal::Bool(val),
1050         }
1051     }
1052 }