]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_def/src/body/lower.rs
Merge #8853
[rust.git] / crates / hir_def / src / body / lower.rs
index d4abe819d37f3a274dd3f9d989a897410f6f3bfb..2a7e0205f5be5da75500a6560a400db0392f9b78 100644 (file)
@@ -1,17 +1,17 @@
 //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
 //! representation.
 
-use std::{any::type_name, mem, sync::Arc};
+use std::{mem, sync::Arc};
 
 use either::Either;
 use hir_expand::{
+    ast_id_map::{AstIdMap, FileAstId},
     hygiene::Hygiene,
     name::{name, AsName, Name},
-    ExpandError, HirFileId, MacroDefId, MacroDefKind,
+    ExpandError, HirFileId,
 };
 use la_arena::Arena;
 use profile::Count;
-use rustc_hash::FxHashMap;
 use syntax::{
     ast::{
         self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner,
     body::{Body, BodySourceMap, Expander, LabelSource, PatPtr, SyntheticSyntax},
     builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
     db::DefDatabase,
-    diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro},
+    diagnostics::{InactiveCode, MacroError, UnresolvedMacroCall, UnresolvedProcMacro},
     expr::{
         dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Label,
         LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
         Statement,
     },
+    intern::Interned,
     item_scope::BuiltinShadowMode,
-    item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
     path::{GenericArgs, Path},
     type_ref::{Mutability, Rawness, TypeRef},
-    AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern,
-    ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
+    AdtId, BlockLoc, ModuleDefId, UnresolvedMacro,
 };
 
 use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
 
-pub(crate) struct LowerCtx {
+pub struct LowerCtx<'a> {
+    pub db: &'a dyn DefDatabase,
     hygiene: Hygiene,
+    file_id: Option<HirFileId>,
+    source_ast_id_map: Option<Arc<AstIdMap>>,
 }
 
-impl LowerCtx {
-    pub(crate) fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self {
-        LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) }
+impl<'a> LowerCtx<'a> {
+    pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
+        LowerCtx {
+            db,
+            hygiene: Hygiene::new(db.upcast(), file_id),
+            file_id: Some(file_id),
+            source_ast_id_map: Some(db.ast_id_map(file_id)),
+        }
+    }
+
+    pub fn with_hygiene(db: &'a dyn DefDatabase, hygiene: &Hygiene) -> Self {
+        LowerCtx { db, hygiene: hygiene.clone(), file_id: None, source_ast_id_map: None }
+    }
+
+    pub(crate) fn hygiene(&self) -> &Hygiene {
+        &self.hygiene
     }
-    pub(crate) fn with_hygiene(hygiene: &Hygiene) -> Self {
-        LowerCtx { hygiene: hygiene.clone() }
+
+    pub(crate) fn file_id(&self) -> HirFileId {
+        self.file_id.unwrap()
     }
 
     pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
-        Path::from_src(ast, &self.hygiene)
+        Path::from_src(ast, self)
+    }
+
+    pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> Option<FileAstId<N>> {
+        self.source_ast_id_map.as_ref().map(|ast_id_map| ast_id_map.ast_id(item))
     }
 }
 
 pub(super) fn lower(
     db: &dyn DefDatabase,
-    def: DefWithBodyId,
     expander: Expander,
     params: Option<ast::ParamList>,
     body: Option<ast::Expr>,
 ) -> (Body, BodySourceMap) {
-    let item_tree = db.item_tree(expander.current_file_id);
     ExprCollector {
         db,
-        def,
         source_map: BodySourceMap::default(),
         body: Body {
             exprs: Arena::default(),
@@ -76,27 +93,21 @@ pub(super) fn lower(
             labels: Arena::default(),
             params: Vec::new(),
             body_expr: dummy_expr_id(),
-            item_scope: Default::default(),
+            block_scopes: Vec::new(),
             _c: Count::new(),
         },
-        item_trees: {
-            let mut map = FxHashMap::default();
-            map.insert(expander.current_file_id, item_tree);
-            map
-        },
         expander,
+        statements_in_scope: Vec::new(),
     }
     .collect(params, body)
 }
 
 struct ExprCollector<'a> {
     db: &'a dyn DefDatabase,
-    def: DefWithBodyId,
     expander: Expander,
     body: Body,
     source_map: BodySourceMap,
-
-    item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
+    statements_in_scope: Vec<Statement>,
 }
 
 impl ExprCollector<'_> {
@@ -136,7 +147,7 @@ fn collect(
         (self.body, self.source_map)
     }
 
-    fn ctx(&self) -> LowerCtx {
+    fn ctx(&self) -> LowerCtx<'_> {
         LowerCtx::new(self.db, self.expander.current_file_id)
     }
 
@@ -191,12 +202,15 @@ fn make_label(&mut self, label: Label, src: LabelSource) -> LabelId {
     }
 
     fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
+        self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
+    }
+
+    /// Returns `None` if and only if the expression is `#[cfg]`d out.
+    fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
         let syntax_ptr = AstPtr::new(&expr);
-        if self.check_cfg(&expr).is_none() {
-            return self.missing_expr();
-        }
+        self.check_cfg(&expr)?;
 
-        match expr {
+        Some(match expr {
             ast::Expr::IfExpr(e) => {
                 let then_branch = self.collect_block_opt(e.then_branch());
 
@@ -225,8 +239,9 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                                     guard: None,
                                 },
                             ];
-                            return self
-                                .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr);
+                            return Some(
+                                self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr),
+                            );
                         }
                     },
                 };
@@ -297,8 +312,9 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                             ];
                             let match_expr =
                                 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
-                            return self
-                                .alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr);
+                            return Some(
+                                self.alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr),
+                            );
                         }
                     },
                 };
@@ -315,7 +331,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
             ast::Expr::CallExpr(e) => {
                 let callee = self.collect_expr_opt(e.expr());
                 let args = if let Some(arg_list) = e.arg_list() {
-                    arg_list.args().map(|e| self.collect_expr(e)).collect()
+                    arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
                 } else {
                     Vec::new()
                 };
@@ -324,13 +340,15 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
             ast::Expr::MethodCallExpr(e) => {
                 let receiver = self.collect_expr_opt(e.receiver());
                 let args = if let Some(arg_list) = e.arg_list() {
-                    arg_list.args().map(|e| self.collect_expr(e)).collect()
+                    arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
                 } else {
                     Vec::new()
                 };
                 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
-                let generic_args =
-                    e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
+                let generic_args = e
+                    .generic_arg_list()
+                    .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
+                    .map(Box::new);
                 self.alloc_expr(
                     Expr::MethodCall { receiver, method_name, args, generic_args },
                     syntax_ptr,
@@ -360,7 +378,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
             ast::Expr::PathExpr(e) => {
                 let path = e
                     .path()
-                    .and_then(|path| self.expander.parse_path(path))
+                    .and_then(|path| self.expander.parse_path(self.db, path))
                     .map(Expr::Path)
                     .unwrap_or(Expr::Missing);
                 self.alloc_expr(path, syntax_ptr)
@@ -392,24 +410,24 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
             }
             ast::Expr::RecordExpr(e) => {
-                let path = e.path().and_then(|path| self.expander.parse_path(path));
-                let mut field_ptrs = Vec::new();
+                let path =
+                    e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
                 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
                     let fields = nfl
                         .fields()
-                        .inspect(|field| field_ptrs.push(AstPtr::new(field)))
                         .filter_map(|field| {
                             self.check_cfg(&field)?;
 
                             let name = field.field_name()?.as_name();
 
-                            Some(RecordLitField {
-                                name,
-                                expr: match field.expr() {
-                                    Some(e) => self.collect_expr(e),
-                                    None => self.missing_expr(),
-                                },
-                            })
+                            let expr = match field.expr() {
+                                Some(e) => self.collect_expr(e),
+                                None => self.missing_expr(),
+                            };
+                            let src = self.expander.to_source(AstPtr::new(&field));
+                            self.source_map.field_map.insert(src.clone(), expr);
+                            self.source_map.field_map_back.insert(expr, src);
+                            Some(RecordLitField { name, expr })
                         })
                         .collect();
                     let spread = nfl.spread().map(|s| self.collect_expr(s));
@@ -418,12 +436,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                     Expr::RecordLit { path, fields: Vec::new(), spread: None }
                 };
 
-                let res = self.alloc_expr(record_lit, syntax_ptr);
-                for (i, ptr) in field_ptrs.into_iter().enumerate() {
-                    let src = self.expander.to_source(ptr);
-                    self.source_map.field_map.insert((res, i), src);
-                }
-                res
+                self.alloc_expr(record_lit, syntax_ptr)
             }
             ast::Expr::FieldExpr(e) => {
                 let expr = self.collect_expr_opt(e.expr());
@@ -443,7 +456,7 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
             }
             ast::Expr::CastExpr(e) => {
                 let expr = self.collect_expr_opt(e.expr());
-                let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty());
+                let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
                 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
             }
             ast::Expr::RefExpr(e) => {
@@ -477,13 +490,16 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                 if let Some(pl) = e.param_list() {
                     for param in pl.params() {
                         let pat = self.collect_pat_opt(param.pat());
-                        let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
+                        let type_ref =
+                            param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
                         args.push(pat);
                         arg_types.push(type_ref);
                     }
                 }
-                let ret_type =
-                    e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it));
+                let ret_type = e
+                    .ret_type()
+                    .and_then(|r| r.ty())
+                    .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
                 let body = self.collect_expr_opt(e.body());
                 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
             }
@@ -538,8 +554,9 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                 }
             }
             ast::Expr::MacroCall(e) => {
+                let macro_ptr = AstPtr::new(&e);
                 let mut ids = vec![];
-                self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| {
+                self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
                     ids.push(match expansion {
                         Some(it) => this.collect_expr(it),
                         None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -547,13 +564,23 @@ fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
                 });
                 ids[0]
             }
-        }
+            ast::Expr::MacroStmts(e) => {
+                e.statements().for_each(|s| self.collect_stmt(s));
+                let tail = e
+                    .expr()
+                    .map(|e| self.collect_expr(e))
+                    .unwrap_or_else(|| self.alloc_expr(Expr::Missing, syntax_ptr.clone()));
+
+                self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr)
+            }
+        })
     }
 
     fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
         &mut self,
         e: ast::MacroCall,
-        syntax_ptr: AstPtr<ast::Expr>,
+        syntax_ptr: AstPtr<ast::MacroCall>,
+        is_error_recoverable: bool,
         mut collector: F,
     ) {
         // File containing the macro call. Expansion errors will be attached here.
@@ -562,6 +589,21 @@ fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
         let macro_call = self.expander.to_source(AstPtr::new(&e));
         let res = self.expander.enter_expand(self.db, e);
 
+        let res = match res {
+            Ok(res) => res,
+            Err(UnresolvedMacro { path }) => {
+                self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall(
+                    UnresolvedMacroCall {
+                        file: outer_file,
+                        node: syntax_ptr.cast().unwrap(),
+                        path,
+                    },
+                ));
+                collector(self, None);
+                return;
+            }
+        };
+
         match &res.err {
             Some(ExpandError::UnresolvedProcMacro) => {
                 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
@@ -587,15 +629,12 @@ fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
             Some((mark, expansion)) => {
                 // FIXME: Statements are too complicated to recover from error for now.
                 // It is because we don't have any hygiene for local variable expansion right now.
-                if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() {
+                if !is_error_recoverable && res.err.is_some() {
                     self.expander.exit(self.db, mark);
                     collector(self, None);
                 } else {
                     self.source_map.expansions.insert(macro_call, self.expander.current_file_id);
 
-                    let item_tree = self.db.item_tree(self.expander.current_file_id);
-                    self.item_trees.insert(self.expander.current_file_id, item_tree);
-
                     let id = collector(self, Some(expansion));
                     self.expander.exit(self.db, mark);
                     id
@@ -605,32 +644,6 @@ fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
         }
     }
 
-    fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
-        let id = self.expander.ast_id(ast);
-        let tree = &self.item_trees[&id.file_id];
-
-        // FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
-
-        // Root file (non-macro).
-        let item_tree_id = tree
-            .all_inner_items()
-            .chain(tree.top_level_items().iter().copied())
-            .filter_map(|mod_item| mod_item.downcast::<N>())
-            .find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
-            .or_else(|| {
-                log::debug!(
-                    "couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
-                    type_name::<N>(),
-                    id,
-                    ast.syntax(),
-                    ast.syntax(),
-                );
-                None
-            })?;
-
-        Some(ItemTreeId::new(id.file_id, item_tree_id))
-    }
-
     fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
         if let Some(expr) = expr {
             self.collect_expr(expr)
@@ -639,60 +652,60 @@ fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
         }
     }
 
-    fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
-        let stmt =
-            match s {
-                ast::Stmt::LetStmt(stmt) => {
-                    self.check_cfg(&stmt)?;
-
-                    let pat = self.collect_pat_opt(stmt.pat());
-                    let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
-                    let initializer = stmt.initializer().map(|e| self.collect_expr(e));
-                    vec![Statement::Let { pat, type_ref, initializer }]
+    fn collect_stmt(&mut self, s: ast::Stmt) {
+        match s {
+            ast::Stmt::LetStmt(stmt) => {
+                if self.check_cfg(&stmt).is_none() {
+                    return;
                 }
-                ast::Stmt::ExprStmt(stmt) => {
-                    self.check_cfg(&stmt)?;
-
-                    // Note that macro could be expended to multiple statements
-                    if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
-                        let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
-                        let mut stmts = vec![];
-
-                        self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| {
-                            match expansion {
-                                Some(expansion) => {
-                                    let statements: ast::MacroStmts = expansion;
-                                    this.collect_stmts_items(statements.statements());
-
-                                    statements.statements().for_each(|stmt| {
-                                        if let Some(mut r) = this.collect_stmt(stmt) {
-                                            stmts.append(&mut r);
-                                        }
-                                    });
-                                    if let Some(expr) = statements.expr() {
-                                        stmts.push(Statement::Expr(this.collect_expr(expr)));
-                                    }
-                                }
-                                None => {
-                                    stmts.push(Statement::Expr(
-                                        this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
-                                    ));
+                let pat = self.collect_pat_opt(stmt.pat());
+                let type_ref =
+                    stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
+                let initializer = stmt.initializer().map(|e| self.collect_expr(e));
+                self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
+            }
+            ast::Stmt::ExprStmt(stmt) => {
+                if self.check_cfg(&stmt).is_none() {
+                    return;
+                }
+                let has_semi = stmt.semicolon_token().is_some();
+                // Note that macro could be expended to multiple statements
+                if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
+                    let macro_ptr = AstPtr::new(&m);
+                    let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
+
+                    self.collect_macro_call(
+                        m,
+                        macro_ptr,
+                        false,
+                        |this, expansion| match expansion {
+                            Some(expansion) => {
+                                let statements: ast::MacroStmts = expansion;
+
+                                statements.statements().for_each(|stmt| this.collect_stmt(stmt));
+                                if let Some(expr) = statements.expr() {
+                                    let expr = this.collect_expr(expr);
+                                    this.statements_in_scope
+                                        .push(Statement::Expr { expr, has_semi });
                                 }
                             }
-                        });
-                        stmts
-                    } else {
-                        vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
-                    }
+                            None => {
+                                let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
+                                this.statements_in_scope.push(Statement::Expr { expr, has_semi });
+                            }
+                        },
+                    );
+                } else {
+                    let expr = self.collect_expr_opt(stmt.expr());
+                    self.statements_in_scope.push(Statement::Expr { expr, has_semi });
                 }
-                ast::Stmt::Item(item) => {
-                    self.check_cfg(&item)?;
-
-                    return None;
+            }
+            ast::Stmt::Item(item) => {
+                if self.check_cfg(&item).is_none() {
+                    return;
                 }
-            };
-
-        Some(stmt)
+            }
+        }
     }
 
     fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
@@ -700,17 +713,31 @@ fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
         let block_loc =
             BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
         let block_id = self.db.intern_block(block_loc);
-        let opt_def_map = self.db.block_def_map(block_id);
-        let has_def_map = opt_def_map.is_some();
-        let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
-        let module = if has_def_map { def_map.root() } else { self.expander.module };
+
+        let (module, def_map) = match self.db.block_def_map(block_id) {
+            Some(def_map) => {
+                self.body.block_scopes.push(block_id);
+                (def_map.root(), def_map)
+            }
+            None => (self.expander.module, self.expander.def_map.clone()),
+        };
         let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
         let prev_local_module = mem::replace(&mut self.expander.module, module);
-
-        self.collect_stmts_items(block.statements());
-        let statements =
-            block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
-        let tail = block.tail_expr().map(|e| self.collect_expr(e));
+        let prev_statements = std::mem::take(&mut self.statements_in_scope);
+
+        block.statements().for_each(|s| self.collect_stmt(s));
+        block.tail_expr().and_then(|e| {
+            let expr = self.maybe_collect_expr(e)?;
+            Some(self.statements_in_scope.push(Statement::Expr { expr, has_semi: false }))
+        });
+
+        let mut tail = None;
+        if let Some(Statement::Expr { expr, has_semi: false }) = self.statements_in_scope.last() {
+            tail = Some(*expr);
+            self.statements_in_scope.pop();
+        }
+        let tail = tail;
+        let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements);
         let syntax_node_ptr = AstPtr::new(&block.into());
         let expr_id = self.alloc_expr(
             Expr::Block { id: block_id, statements, tail, label: None },
@@ -722,108 +749,6 @@ fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
         expr_id
     }
 
-    fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
-        let container = ContainerId::DefWithBodyId(self.def);
-
-        let items = stmts
-            .filter_map(|stmt| match stmt {
-                ast::Stmt::Item(it) => Some(it),
-                ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
-            })
-            .filter_map(|item| {
-                let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
-                    ast::Item::Fn(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (
-                            FunctionLoc { container: container.into(), id }.intern(self.db).into(),
-                            def.name(),
-                        )
-                    }
-                    ast::Item::TypeAlias(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (
-                            TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
-                            def.name(),
-                        )
-                    }
-                    ast::Item::Const(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (
-                            ConstLoc { container: container.into(), id }.intern(self.db).into(),
-                            def.name(),
-                        )
-                    }
-                    ast::Item::Static(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (StaticLoc { container, id }.intern(self.db).into(), def.name())
-                    }
-                    ast::Item::Struct(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (StructLoc { container, id }.intern(self.db).into(), def.name())
-                    }
-                    ast::Item::Enum(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (EnumLoc { container, id }.intern(self.db).into(), def.name())
-                    }
-                    ast::Item::Union(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (UnionLoc { container, id }.intern(self.db).into(), def.name())
-                    }
-                    ast::Item::Trait(def) => {
-                        let id = self.find_inner_item(&def)?;
-                        (TraitLoc { container, id }.intern(self.db).into(), def.name())
-                    }
-                    ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
-                    ast::Item::Impl(_)
-                    | ast::Item::Use(_)
-                    | ast::Item::ExternCrate(_)
-                    | ast::Item::Module(_)
-                    | ast::Item::MacroCall(_) => return None,
-                    ast::Item::MacroRules(def) => {
-                        return Some(Either::Right(ast::Macro::from(def)));
-                    }
-                    ast::Item::MacroDef(def) => {
-                        return Some(Either::Right(ast::Macro::from(def)));
-                    }
-                };
-
-                Some(Either::Left((def, name)))
-            })
-            .collect::<Vec<_>>();
-
-        for either in items {
-            match either {
-                Either::Left((def, name)) => {
-                    self.body.item_scope.define_def(def);
-                    if let Some(name) = name {
-                        let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
-                        let has_constructor = match def {
-                            ModuleDefId::AdtId(AdtId::StructId(s)) => {
-                                self.db.struct_data(s).variant_data.kind() != StructKind::Record
-                            }
-                            _ => true,
-                        };
-                        self.body.item_scope.push_res(
-                            name.as_name(),
-                            crate::per_ns::PerNs::from_def(def, vis, has_constructor),
-                        );
-                    }
-                }
-                Either::Right(e) => {
-                    let mac = MacroDefId {
-                        krate: self.expander.def_map.krate(),
-                        ast_id: Some(self.expander.ast_id(&e)),
-                        kind: MacroDefKind::Declarative,
-                        local_inner: false,
-                    };
-                    if let Some(name) = e.name() {
-                        self.body.item_scope.define_legacy_macro(name.as_name(), mac);
-                    }
-                }
-            }
-        }
-    }
-
     fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
         if let Some(block) = expr {
             self.collect_block(block)
@@ -879,7 +804,8 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
                 }
             }
             ast::Pat::TupleStructPat(p) => {
-                let path = p.path().and_then(|path| self.expander.parse_path(path));
+                let path =
+                    p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
                 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
                 Pat::TupleStruct { path, args, ellipsis }
             }
@@ -889,7 +815,8 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
                 Pat::Ref { pat, mutability }
             }
             ast::Pat::PathPat(p) => {
-                let path = p.path().and_then(|path| self.expander.parse_path(path));
+                let path =
+                    p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
                 path.map(Pat::Path).unwrap_or(Pat::Missing)
             }
             ast::Pat::OrPat(p) => {
@@ -903,7 +830,8 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
             }
             ast::Pat::WildcardPat(_) => Pat::Wild,
             ast::Pat::RecordPat(p) => {
-                let path = p.path().and_then(|path| self.expander.parse_path(path));
+                let path =
+                    p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
                 let args: Vec<_> = p
                     .record_pat_field_list()
                     .expect("every struct should have a field list")
@@ -965,8 +893,23 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
                     Pat::Missing
                 }
             }
+            ast::Pat::MacroPat(mac) => match mac.macro_call() {
+                Some(call) => {
+                    let macro_ptr = AstPtr::new(&call);
+                    let mut pat = None;
+                    self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
+                        pat = Some(this.collect_pat_opt(expanded_pat));
+                    });
+
+                    match pat {
+                        Some(pat) => return pat,
+                        None => Pat::Missing,
+                    }
+                }
+                None => Pat::Missing,
+            },
             // FIXME: implement
-            ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
+            ast::Pat::RangePat(_) => Pat::Missing,
         };
         let ptr = AstPtr::new(&pat);
         self.alloc_pat(pattern, Either::Left(ptr))
@@ -1063,23 +1006,27 @@ fn from(ast_op: ast::BinOp) -> Self {
 impl From<ast::LiteralKind> for Literal {
     fn from(ast_lit_kind: ast::LiteralKind) -> Self {
         match ast_lit_kind {
+            // FIXME: these should have actual values filled in, but unsure on perf impact
             LiteralKind::IntNumber(lit) => {
                 if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
                     return Literal::Float(Default::default(), builtin);
                 } else if let builtin @ Some(_) =
                     lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it))
                 {
-                    Literal::Int(Default::default(), builtin)
+                    Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
                 } else {
                     let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it));
-                    Literal::Uint(Default::default(), builtin)
+                    Literal::Uint(lit.value().unwrap_or(0), builtin)
                 }
             }
             LiteralKind::FloatNumber(lit) => {
                 let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it));
                 Literal::Float(Default::default(), ty)
             }
-            LiteralKind::ByteString(_) => Literal::ByteString(Default::default()),
+            LiteralKind::ByteString(bs) => {
+                let text = bs.value().map(Vec::from).unwrap_or_else(Default::default);
+                Literal::ByteString(text)
+            }
             LiteralKind::String(_) => Literal::String(Default::default()),
             LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)),
             LiteralKind::Bool(val) => Literal::Bool(val),