aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/body/lower.rs')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs916
1 files changed, 0 insertions, 916 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
deleted file mode 100644
index 827ced4ad..000000000
--- a/crates/ra_hir_def/src/body/lower.rs
+++ /dev/null
@@ -1,916 +0,0 @@
1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2//! representation.
3
4use either::Either;
5use hir_expand::{
6 hygiene::Hygiene,
7 name::{name, AsName, Name},
8 HirFileId, MacroDefId, MacroDefKind,
9};
10use ra_arena::Arena;
11use ra_syntax::{
12 ast::{
13 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
14 SlicePatComponents,
15 },
16 AstNode, AstPtr,
17};
18use test_utils::mark;
19
20use crate::{
21 adt::StructKind,
22 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
23 builtin_type::{BuiltinFloat, BuiltinInt},
24 db::DefDatabase,
25 expr::{
26 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal,
27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
28 },
29 item_scope::BuiltinShadowMode,
30 item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
31 path::{GenericArgs, Path},
32 type_ref::{Mutability, Rawness, TypeRef},
33 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
34 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
35};
36
37use super::{ExprSource, PatSource};
38use ast::AstChildren;
39use rustc_hash::FxHashMap;
40use std::{any::type_name, sync::Arc};
41
42pub(crate) struct LowerCtx {
43 hygiene: Hygiene,
44}
45
46impl LowerCtx {
47 pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self {
48 LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) }
49 }
50 pub fn with_hygiene(hygiene: &Hygiene) -> Self {
51 LowerCtx { hygiene: hygiene.clone() }
52 }
53
54 pub fn lower_path(&self, ast: ast::Path) -> Option<Path> {
55 Path::from_src(ast, &self.hygiene)
56 }
57}
58
59pub(super) fn lower(
60 db: &dyn DefDatabase,
61 def: DefWithBodyId,
62 expander: Expander,
63 params: Option<ast::ParamList>,
64 body: Option<ast::Expr>,
65) -> (Body, BodySourceMap) {
66 let item_tree = db.item_tree(expander.current_file_id);
67 ExprCollector {
68 db,
69 def,
70 source_map: BodySourceMap::default(),
71 body: Body {
72 exprs: Arena::default(),
73 pats: Arena::default(),
74 params: Vec::new(),
75 body_expr: dummy_expr_id(),
76 item_scope: Default::default(),
77 },
78 item_trees: {
79 let mut map = FxHashMap::default();
80 map.insert(expander.current_file_id, item_tree);
81 map
82 },
83 expander,
84 }
85 .collect(params, body)
86}
87
88struct ExprCollector<'a> {
89 db: &'a dyn DefDatabase,
90 def: DefWithBodyId,
91 expander: Expander,
92 body: Body,
93 source_map: BodySourceMap,
94
95 item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
96}
97
98impl ExprCollector<'_> {
99 fn collect(
100 mut self,
101 param_list: Option<ast::ParamList>,
102 body: Option<ast::Expr>,
103 ) -> (Body, BodySourceMap) {
104 if let Some(param_list) = param_list {
105 if let Some(self_param) = param_list.self_param() {
106 let ptr = AstPtr::new(&self_param);
107 let param_pat = self.alloc_pat(
108 Pat::Bind {
109 name: name![self],
110 mode: BindingAnnotation::Unannotated,
111 subpat: None,
112 },
113 Either::Right(ptr),
114 );
115 self.body.params.push(param_pat);
116 }
117
118 for param in param_list.params() {
119 let pat = match param.pat() {
120 None => continue,
121 Some(pat) => pat,
122 };
123 let param_pat = self.collect_pat(pat);
124 self.body.params.push(param_pat);
125 }
126 };
127
128 self.body.body_expr = self.collect_expr_opt(body);
129 (self.body, self.source_map)
130 }
131
132 fn ctx(&self) -> LowerCtx {
133 LowerCtx::new(self.db, self.expander.current_file_id)
134 }
135
136 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
137 let src = self.expander.to_source(ptr);
138 let id = self.make_expr(expr, Ok(src.clone()));
139 self.source_map.expr_map.insert(src, id);
140 id
141 }
142 // desugared exprs don't have ptr, that's wrong and should be fixed
143 // somehow.
144 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
145 self.make_expr(expr, Err(SyntheticSyntax))
146 }
147 fn empty_block(&mut self) -> ExprId {
148 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None })
149 }
150 fn missing_expr(&mut self) -> ExprId {
151 self.alloc_expr_desugared(Expr::Missing)
152 }
153 fn make_expr(&mut self, expr: Expr, src: Result<ExprSource, SyntheticSyntax>) -> ExprId {
154 let id = self.body.exprs.alloc(expr);
155 self.source_map.expr_map_back.insert(id, src);
156 id
157 }
158
159 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
160 let src = self.expander.to_source(ptr);
161 let id = self.make_pat(pat, Ok(src.clone()));
162 self.source_map.pat_map.insert(src, id);
163 id
164 }
165 fn missing_pat(&mut self) -> PatId {
166 self.make_pat(Pat::Missing, Err(SyntheticSyntax))
167 }
168 fn make_pat(&mut self, pat: Pat, src: Result<PatSource, SyntheticSyntax>) -> PatId {
169 let id = self.body.pats.alloc(pat);
170 self.source_map.pat_map_back.insert(id, src);
171 id
172 }
173
174 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
175 let syntax_ptr = AstPtr::new(&expr);
176 if !self.expander.is_cfg_enabled(&expr) {
177 return self.missing_expr();
178 }
179
180 match expr {
181 ast::Expr::IfExpr(e) => {
182 let then_branch = self.collect_block_opt(e.then_branch());
183
184 let else_branch = e.else_branch().map(|b| match b {
185 ast::ElseBranch::Block(it) => self.collect_block(it),
186 ast::ElseBranch::IfExpr(elif) => {
187 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
188 self.collect_expr(expr)
189 }
190 });
191
192 let condition = match e.condition() {
193 None => self.missing_expr(),
194 Some(condition) => match condition.pat() {
195 None => self.collect_expr_opt(condition.expr()),
196 // if let -- desugar to match
197 Some(pat) => {
198 let pat = self.collect_pat(pat);
199 let match_expr = self.collect_expr_opt(condition.expr());
200 let placeholder_pat = self.missing_pat();
201 let arms = vec![
202 MatchArm { pat, expr: then_branch, guard: None },
203 MatchArm {
204 pat: placeholder_pat,
205 expr: else_branch.unwrap_or_else(|| self.empty_block()),
206 guard: None,
207 },
208 ];
209 return self
210 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
211 }
212 },
213 };
214
215 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
216 }
217 ast::Expr::EffectExpr(e) => match e.effect() {
218 ast::Effect::Try(_) => {
219 let body = self.collect_block_opt(e.block_expr());
220 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
221 }
222 ast::Effect::Unsafe(_) => {
223 let body = self.collect_block_opt(e.block_expr());
224 self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
225 }
226 // FIXME: we need to record these effects somewhere...
227 ast::Effect::Async(_) | ast::Effect::Label(_) => {
228 self.collect_block_opt(e.block_expr())
229 }
230 },
231 ast::Expr::BlockExpr(e) => self.collect_block(e),
232 ast::Expr::LoopExpr(e) => {
233 let body = self.collect_block_opt(e.loop_body());
234 self.alloc_expr(
235 Expr::Loop {
236 body,
237 label: e
238 .label()
239 .and_then(|l| l.lifetime_token())
240 .map(|l| Name::new_lifetime(&l)),
241 },
242 syntax_ptr,
243 )
244 }
245 ast::Expr::WhileExpr(e) => {
246 let body = self.collect_block_opt(e.loop_body());
247
248 let condition = match e.condition() {
249 None => self.missing_expr(),
250 Some(condition) => match condition.pat() {
251 None => self.collect_expr_opt(condition.expr()),
252 // if let -- desugar to match
253 Some(pat) => {
254 mark::hit!(infer_resolve_while_let);
255 let pat = self.collect_pat(pat);
256 let match_expr = self.collect_expr_opt(condition.expr());
257 let placeholder_pat = self.missing_pat();
258 let break_ =
259 self.alloc_expr_desugared(Expr::Break { expr: None, label: None });
260 let arms = vec![
261 MatchArm { pat, expr: body, guard: None },
262 MatchArm { pat: placeholder_pat, expr: break_, guard: None },
263 ];
264 let match_expr =
265 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
266 return self.alloc_expr(
267 Expr::Loop {
268 body: match_expr,
269 label: e
270 .label()
271 .and_then(|l| l.lifetime_token())
272 .map(|l| Name::new_lifetime(&l)),
273 },
274 syntax_ptr,
275 );
276 }
277 },
278 };
279
280 self.alloc_expr(
281 Expr::While {
282 condition,
283 body,
284 label: e
285 .label()
286 .and_then(|l| l.lifetime_token())
287 .map(|l| Name::new_lifetime(&l)),
288 },
289 syntax_ptr,
290 )
291 }
292 ast::Expr::ForExpr(e) => {
293 let iterable = self.collect_expr_opt(e.iterable());
294 let pat = self.collect_pat_opt(e.pat());
295 let body = self.collect_block_opt(e.loop_body());
296 self.alloc_expr(
297 Expr::For {
298 iterable,
299 pat,
300 body,
301 label: e
302 .label()
303 .and_then(|l| l.lifetime_token())
304 .map(|l| Name::new_lifetime(&l)),
305 },
306 syntax_ptr,
307 )
308 }
309 ast::Expr::CallExpr(e) => {
310 let callee = self.collect_expr_opt(e.expr());
311 let args = if let Some(arg_list) = e.arg_list() {
312 arg_list.args().map(|e| self.collect_expr(e)).collect()
313 } else {
314 Vec::new()
315 };
316 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
317 }
318 ast::Expr::MethodCallExpr(e) => {
319 let receiver = self.collect_expr_opt(e.expr());
320 let args = if let Some(arg_list) = e.arg_list() {
321 arg_list.args().map(|e| self.collect_expr(e)).collect()
322 } else {
323 Vec::new()
324 };
325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
326 let generic_args =
327 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
328 self.alloc_expr(
329 Expr::MethodCall { receiver, method_name, args, generic_args },
330 syntax_ptr,
331 )
332 }
333 ast::Expr::MatchExpr(e) => {
334 let expr = self.collect_expr_opt(e.expr());
335 let arms = if let Some(match_arm_list) = e.match_arm_list() {
336 match_arm_list
337 .arms()
338 .map(|arm| MatchArm {
339 pat: self.collect_pat_opt(arm.pat()),
340 expr: self.collect_expr_opt(arm.expr()),
341 guard: arm
342 .guard()
343 .and_then(|guard| guard.expr())
344 .map(|e| self.collect_expr(e)),
345 })
346 .collect()
347 } else {
348 Vec::new()
349 };
350 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
351 }
352 ast::Expr::PathExpr(e) => {
353 let path = e
354 .path()
355 .and_then(|path| self.expander.parse_path(path))
356 .map(Expr::Path)
357 .unwrap_or(Expr::Missing);
358 self.alloc_expr(path, syntax_ptr)
359 }
360 ast::Expr::ContinueExpr(e) => self.alloc_expr(
361 Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
362 syntax_ptr,
363 ),
364 ast::Expr::BreakExpr(e) => {
365 let expr = e.expr().map(|e| self.collect_expr(e));
366 self.alloc_expr(
367 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
368 syntax_ptr,
369 )
370 }
371 ast::Expr::ParenExpr(e) => {
372 let inner = self.collect_expr_opt(e.expr());
373 // make the paren expr point to the inner expression as well
374 let src = self.expander.to_source(syntax_ptr);
375 self.source_map.expr_map.insert(src, inner);
376 inner
377 }
378 ast::Expr::ReturnExpr(e) => {
379 let expr = e.expr().map(|e| self.collect_expr(e));
380 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
381 }
382 ast::Expr::RecordExpr(e) => {
383 let path = e.path().and_then(|path| self.expander.parse_path(path));
384 let mut field_ptrs = Vec::new();
385 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
386 let fields = nfl
387 .fields()
388 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
389 .filter_map(|field| {
390 if !self.expander.is_cfg_enabled(&field) {
391 return None;
392 }
393 let name = field.field_name()?.as_name();
394
395 Some(RecordLitField {
396 name,
397 expr: match field.expr() {
398 Some(e) => self.collect_expr(e),
399 None => self.missing_expr(),
400 },
401 })
402 })
403 .collect();
404 let spread = nfl.spread().map(|s| self.collect_expr(s));
405 Expr::RecordLit { path, fields, spread }
406 } else {
407 Expr::RecordLit { path, fields: Vec::new(), spread: None }
408 };
409
410 let res = self.alloc_expr(record_lit, syntax_ptr);
411 for (i, ptr) in field_ptrs.into_iter().enumerate() {
412 let src = self.expander.to_source(ptr);
413 self.source_map.field_map.insert((res, i), src);
414 }
415 res
416 }
417 ast::Expr::FieldExpr(e) => {
418 let expr = self.collect_expr_opt(e.expr());
419 let name = match e.field_access() {
420 Some(kind) => kind.as_name(),
421 _ => Name::missing(),
422 };
423 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
424 }
425 ast::Expr::AwaitExpr(e) => {
426 let expr = self.collect_expr_opt(e.expr());
427 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
428 }
429 ast::Expr::TryExpr(e) => {
430 let expr = self.collect_expr_opt(e.expr());
431 self.alloc_expr(Expr::Try { expr }, syntax_ptr)
432 }
433 ast::Expr::CastExpr(e) => {
434 let expr = self.collect_expr_opt(e.expr());
435 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty());
436 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
437 }
438 ast::Expr::RefExpr(e) => {
439 let expr = self.collect_expr_opt(e.expr());
440 let raw_tok = e.raw_token().is_some();
441 let mutability = if raw_tok {
442 if e.mut_token().is_some() {
443 Mutability::Mut
444 } else if e.const_token().is_some() {
445 Mutability::Shared
446 } else {
447 unreachable!("parser only remaps to raw_token() if matching mutability token follows")
448 }
449 } else {
450 Mutability::from_mutable(e.mut_token().is_some())
451 };
452 let rawness = Rawness::from_raw(raw_tok);
453 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
454 }
455 ast::Expr::PrefixExpr(e) => {
456 let expr = self.collect_expr_opt(e.expr());
457 if let Some(op) = e.op_kind() {
458 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
459 } else {
460 self.alloc_expr(Expr::Missing, syntax_ptr)
461 }
462 }
463 ast::Expr::LambdaExpr(e) => {
464 let mut args = Vec::new();
465 let mut arg_types = Vec::new();
466 if let Some(pl) = e.param_list() {
467 for param in pl.params() {
468 let pat = self.collect_pat_opt(param.pat());
469 let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
470 args.push(pat);
471 arg_types.push(type_ref);
472 }
473 }
474 let ret_type =
475 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it));
476 let body = self.collect_expr_opt(e.body());
477 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
478 }
479 ast::Expr::BinExpr(e) => {
480 let lhs = self.collect_expr_opt(e.lhs());
481 let rhs = self.collect_expr_opt(e.rhs());
482 let op = e.op_kind().map(BinaryOp::from);
483 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
484 }
485 ast::Expr::TupleExpr(e) => {
486 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
487 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
488 }
489 ast::Expr::BoxExpr(e) => {
490 let expr = self.collect_expr_opt(e.expr());
491 self.alloc_expr(Expr::Box { expr }, syntax_ptr)
492 }
493
494 ast::Expr::ArrayExpr(e) => {
495 let kind = e.kind();
496
497 match kind {
498 ArrayExprKind::ElementList(e) => {
499 let exprs = e.map(|expr| self.collect_expr(expr)).collect();
500 self.alloc_expr(Expr::Array(Array::ElementList(exprs)), syntax_ptr)
501 }
502 ArrayExprKind::Repeat { initializer, repeat } => {
503 let initializer = self.collect_expr_opt(initializer);
504 let repeat = self.collect_expr_opt(repeat);
505 self.alloc_expr(
506 Expr::Array(Array::Repeat { initializer, repeat }),
507 syntax_ptr,
508 )
509 }
510 }
511 }
512
513 ast::Expr::Literal(e) => self.alloc_expr(Expr::Literal(e.kind().into()), syntax_ptr),
514 ast::Expr::IndexExpr(e) => {
515 let base = self.collect_expr_opt(e.base());
516 let index = self.collect_expr_opt(e.index());
517 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
518 }
519 ast::Expr::RangeExpr(e) => {
520 let lhs = e.start().map(|lhs| self.collect_expr(lhs));
521 let rhs = e.end().map(|rhs| self.collect_expr(rhs));
522 match e.op_kind() {
523 Some(range_type) => {
524 self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr)
525 }
526 None => self.alloc_expr(Expr::Missing, syntax_ptr),
527 }
528 }
529 ast::Expr::MacroCall(e) => {
530 if let Some(name) = e.is_macro_rules().map(|it| it.as_name()) {
531 let mac = MacroDefId {
532 krate: Some(self.expander.module.krate),
533 ast_id: Some(self.expander.ast_id(&e)),
534 kind: MacroDefKind::Declarative,
535 local_inner: false,
536 };
537 self.body.item_scope.define_legacy_macro(name, mac);
538
539 // FIXME: do we still need to allocate this as missing ?
540 self.alloc_expr(Expr::Missing, syntax_ptr)
541 } else {
542 let macro_call = self.expander.to_source(AstPtr::new(&e));
543 match self.expander.enter_expand(self.db, Some(&self.body.item_scope), e) {
544 Some((mark, expansion)) => {
545 self.source_map
546 .expansions
547 .insert(macro_call, self.expander.current_file_id);
548
549 let item_tree = self.db.item_tree(self.expander.current_file_id);
550 self.item_trees.insert(self.expander.current_file_id, item_tree);
551 let id = self.collect_expr(expansion);
552 self.expander.exit(self.db, mark);
553 id
554 }
555 None => self.alloc_expr(Expr::Missing, syntax_ptr),
556 }
557 }
558 }
559
560 // FIXME implement HIR for these:
561 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
562 }
563 }
564
565 fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
566 let id = self.expander.ast_id(ast);
567 let tree = &self.item_trees[&id.file_id];
568
569 // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
570
571 // Root file (non-macro).
572 let item_tree_id = tree
573 .all_inner_items()
574 .chain(tree.top_level_items().iter().copied())
575 .filter_map(|mod_item| mod_item.downcast::<N>())
576 .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
577 .or_else(|| {
578 log::debug!(
579 "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
580 type_name::<N>(),
581 id,
582 ast.syntax(),
583 ast.syntax(),
584 );
585 None
586 })?;
587
588 Some(ItemTreeId::new(id.file_id, item_tree_id))
589 }
590
591 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
592 if let Some(expr) = expr {
593 self.collect_expr(expr)
594 } else {
595 self.missing_expr()
596 }
597 }
598
599 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
600 let syntax_node_ptr = AstPtr::new(&block.clone().into());
601 self.collect_block_items(&block);
602 let statements = block
603 .statements()
604 .map(|s| match s {
605 ast::Stmt::LetStmt(stmt) => {
606 let pat = self.collect_pat_opt(stmt.pat());
607 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
608 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
609 Statement::Let { pat, type_ref, initializer }
610 }
611 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
612 })
613 .collect();
614 let tail = block.expr().map(|e| self.collect_expr(e));
615 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t));
616 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
617 }
618
619 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
620 let container = ContainerId::DefWithBodyId(self.def);
621
622 let items = block
623 .items()
624 .filter_map(|item| {
625 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
626 ast::Item::Fn(def) => {
627 let id = self.find_inner_item(&def)?;
628 (
629 FunctionLoc { container: container.into(), id }.intern(self.db).into(),
630 def.name(),
631 )
632 }
633 ast::Item::TypeAlias(def) => {
634 let id = self.find_inner_item(&def)?;
635 (
636 TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
637 def.name(),
638 )
639 }
640 ast::Item::Const(def) => {
641 let id = self.find_inner_item(&def)?;
642 (
643 ConstLoc { container: container.into(), id }.intern(self.db).into(),
644 def.name(),
645 )
646 }
647 ast::Item::Static(def) => {
648 let id = self.find_inner_item(&def)?;
649 (StaticLoc { container, id }.intern(self.db).into(), def.name())
650 }
651 ast::Item::Struct(def) => {
652 let id = self.find_inner_item(&def)?;
653 (StructLoc { container, id }.intern(self.db).into(), def.name())
654 }
655 ast::Item::Enum(def) => {
656 let id = self.find_inner_item(&def)?;
657 (EnumLoc { container, id }.intern(self.db).into(), def.name())
658 }
659 ast::Item::Union(def) => {
660 let id = self.find_inner_item(&def)?;
661 (UnionLoc { container, id }.intern(self.db).into(), def.name())
662 }
663 ast::Item::Trait(def) => {
664 let id = self.find_inner_item(&def)?;
665 (TraitLoc { container, id }.intern(self.db).into(), def.name())
666 }
667 ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
668 ast::Item::Impl(_)
669 | ast::Item::Use(_)
670 | ast::Item::ExternCrate(_)
671 | ast::Item::Module(_)
672 | ast::Item::MacroCall(_) => return None,
673 };
674
675 Some((def, name))
676 })
677 .collect::<Vec<_>>();
678
679 for (def, name) in items {
680 self.body.item_scope.define_def(def);
681 if let Some(name) = name {
682 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
683 let has_constructor = match def {
684 ModuleDefId::AdtId(AdtId::StructId(s)) => {
685 self.db.struct_data(s).variant_data.kind() != StructKind::Record
686 }
687 _ => true,
688 };
689 self.body.item_scope.push_res(
690 name.as_name(),
691 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
692 );
693 }
694 }
695 }
696
697 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
698 if let Some(block) = expr {
699 self.collect_block(block)
700 } else {
701 self.missing_expr()
702 }
703 }
704
705 fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
706 let pattern = match &pat {
707 ast::Pat::BindPat(bp) => {
708 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
709 let annotation =
710 BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
711 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
712 if annotation == BindingAnnotation::Unannotated && subpat.is_none() {
713 // This could also be a single-segment path pattern. To
714 // decide that, we need to try resolving the name.
715 let (resolved, _) = self.expander.crate_def_map.resolve_path(
716 self.db,
717 self.expander.module.local_id,
718 &name.clone().into(),
719 BuiltinShadowMode::Other,
720 );
721 match resolved.take_values() {
722 Some(ModuleDefId::ConstId(_)) => Pat::Path(name.into()),
723 Some(ModuleDefId::EnumVariantId(_)) => {
724 // this is only really valid for unit variants, but
725 // shadowing other enum variants with a pattern is
726 // an error anyway
727 Pat::Path(name.into())
728 }
729 Some(ModuleDefId::AdtId(AdtId::StructId(s)))
730 if self.db.struct_data(s).variant_data.kind() != StructKind::Record =>
731 {
732 // Funnily enough, record structs *can* be shadowed
733 // by pattern bindings (but unit or tuple structs
734 // can't).
735 Pat::Path(name.into())
736 }
737 // shadowing statics is an error as well, so we just ignore that case here
738 _ => Pat::Bind { name, mode: annotation, subpat },
739 }
740 } else {
741 Pat::Bind { name, mode: annotation, subpat }
742 }
743 }
744 ast::Pat::TupleStructPat(p) => {
745 let path = p.path().and_then(|path| self.expander.parse_path(path));
746 let (args, ellipsis) = self.collect_tuple_pat(p.args());
747 Pat::TupleStruct { path, args, ellipsis }
748 }
749 ast::Pat::RefPat(p) => {
750 let pat = self.collect_pat_opt(p.pat());
751 let mutability = Mutability::from_mutable(p.mut_token().is_some());
752 Pat::Ref { pat, mutability }
753 }
754 ast::Pat::PathPat(p) => {
755 let path = p.path().and_then(|path| self.expander.parse_path(path));
756 path.map(Pat::Path).unwrap_or(Pat::Missing)
757 }
758 ast::Pat::OrPat(p) => {
759 let pats = p.pats().map(|p| self.collect_pat(p)).collect();
760 Pat::Or(pats)
761 }
762 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()),
763 ast::Pat::TuplePat(p) => {
764 let (args, ellipsis) = self.collect_tuple_pat(p.args());
765 Pat::Tuple { args, ellipsis }
766 }
767 ast::Pat::PlaceholderPat(_) => Pat::Wild,
768 ast::Pat::RecordPat(p) => {
769 let path = p.path().and_then(|path| self.expander.parse_path(path));
770 let record_field_pat_list =
771 p.record_field_pat_list().expect("every struct should have a field list");
772 let mut fields: Vec<_> = record_field_pat_list
773 .bind_pats()
774 .filter_map(|bind_pat| {
775 let ast_pat =
776 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
777 let pat = self.collect_pat(ast_pat);
778 let name = bind_pat.name()?.as_name();
779 Some(RecordFieldPat { name, pat })
780 })
781 .collect();
782 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
783 let ast_pat = f.pat()?;
784 let pat = self.collect_pat(ast_pat);
785 let name = f.field_name()?.as_name();
786 Some(RecordFieldPat { name, pat })
787 });
788 fields.extend(iter);
789
790 let ellipsis = record_field_pat_list.dotdot_token().is_some();
791
792 Pat::Record { path, args: fields, ellipsis }
793 }
794 ast::Pat::SlicePat(p) => {
795 let SlicePatComponents { prefix, slice, suffix } = p.components();
796
797 // FIXME properly handle `DotDotPat`
798 Pat::Slice {
799 prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(),
800 slice: slice.map(|p| self.collect_pat(p)),
801 suffix: suffix.into_iter().map(|p| self.collect_pat(p)).collect(),
802 }
803 }
804 ast::Pat::LiteralPat(lit) => {
805 if let Some(ast_lit) = lit.literal() {
806 let expr = Expr::Literal(ast_lit.kind().into());
807 let expr_ptr = AstPtr::new(&ast::Expr::Literal(ast_lit));
808 let expr_id = self.alloc_expr(expr, expr_ptr);
809 Pat::Lit(expr_id)
810 } else {
811 Pat::Missing
812 }
813 }
814 ast::Pat::DotDotPat(_) => {
815 // `DotDotPat` requires special handling and should not be mapped
816 // to a Pat. Here we are using `Pat::Missing` as a fallback for
817 // when `DotDotPat` is mapped to `Pat`, which can easily happen
818 // when the source code being analyzed has a malformed pattern
819 // which includes `..` in a place where it isn't valid.
820
821 Pat::Missing
822 }
823 // FIXME: implement
824 ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
825 };
826 let ptr = AstPtr::new(&pat);
827 self.alloc_pat(pattern, Either::Left(ptr))
828 }
829
830 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
831 if let Some(pat) = pat {
832 self.collect_pat(pat)
833 } else {
834 self.missing_pat()
835 }
836 }
837
838 fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) {
839 // Find the location of the `..`, if there is one. Note that we do not
840 // consider the possiblity of there being multiple `..` here.
841 let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_)));
842 // We want to skip the `..` pattern here, since we account for it above.
843 let args = args
844 .filter(|p| !matches!(p, ast::Pat::DotDotPat(_)))
845 .map(|p| self.collect_pat(p))
846 .collect();
847
848 (args, ellipsis)
849 }
850}
851
852impl From<ast::BinOp> for BinaryOp {
853 fn from(ast_op: ast::BinOp) -> Self {
854 match ast_op {
855 ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
856 ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
857 ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
858 ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
859 ast::BinOp::LesserEqualTest => {
860 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
861 }
862 ast::BinOp::GreaterEqualTest => {
863 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
864 }
865 ast::BinOp::LesserTest => {
866 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
867 }
868 ast::BinOp::GreaterTest => {
869 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
870 }
871 ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
872 ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
873 ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
874 ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
875 ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
876 ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
877 ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
878 ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
879 ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
880 ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
881 ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
882 ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
883 ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
884 ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
885 ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
886 ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
887 ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
888 ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
889 ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
890 ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
891 ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
892 }
893 }
894}
895
896impl From<ast::LiteralKind> for Literal {
897 fn from(ast_lit_kind: ast::LiteralKind) -> Self {
898 match ast_lit_kind {
899 LiteralKind::IntNumber { suffix } => {
900 let known_name = suffix.and_then(|it| BuiltinInt::from_suffix(&it));
901
902 Literal::Int(Default::default(), known_name)
903 }
904 LiteralKind::FloatNumber { suffix } => {
905 let known_name = suffix.and_then(|it| BuiltinFloat::from_suffix(&it));
906
907 Literal::Float(Default::default(), known_name)
908 }
909 LiteralKind::ByteString => Literal::ByteString(Default::default()),
910 LiteralKind::String => Literal::String(Default::default()),
911 LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)),
912 LiteralKind::Bool(val) => Literal::Bool(val),
913 LiteralKind::Char => Literal::Char(Default::default()),
914 }
915 }
916}