aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/attr.rs105
-rw-r--r--crates/hir_def/src/body/lower.rs63
-rw-r--r--crates/hir_def/src/body/tests.rs2
-rw-r--r--crates/hir_def/src/child_by_source.rs4
-rw-r--r--crates/hir_def/src/db.rs15
-rw-r--r--crates/hir_def/src/expr.rs19
-rw-r--r--crates/hir_def/src/item_scope.rs13
-rw-r--r--crates/hir_def/src/item_tree.rs5
-rw-r--r--crates/hir_def/src/item_tree/lower.rs2
-rw-r--r--crates/hir_def/src/lib.rs34
-rw-r--r--crates/hir_def/src/nameres.rs28
-rw-r--r--crates/hir_def/src/nameres/collector.rs59
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs51
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs2
-rw-r--r--crates/hir_def/src/path.rs6
15 files changed, 288 insertions, 120 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index ab77d924a..786fad6e1 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -9,14 +9,14 @@ use std::{
9use base_db::CrateId; 9use base_db::CrateId;
10use cfg::{CfgExpr, CfgOptions}; 10use cfg::{CfgExpr, CfgOptions};
11use either::Either; 11use either::Either;
12use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; 12use hir_expand::{hygiene::Hygiene, name::AsName, AstId, AttrId, InFile};
13use itertools::Itertools; 13use itertools::Itertools;
14use la_arena::ArenaMap; 14use la_arena::ArenaMap;
15use mbe::ast_to_token_tree; 15use mbe::ast_to_token_tree;
16use smallvec::{smallvec, SmallVec}; 16use smallvec::{smallvec, SmallVec};
17use syntax::{ 17use syntax::{
18 ast::{self, AstNode, AttrsOwner}, 18 ast::{self, AstNode, AttrsOwner},
19 match_ast, AstToken, SmolStr, SyntaxNode, TextRange, TextSize, 19 match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
20}; 20};
21use tt::Subtree; 21use tt::Subtree;
22 22
@@ -98,13 +98,16 @@ impl RawAttrs {
98 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self { 98 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self {
99 let entries = collect_attrs(owner) 99 let entries = collect_attrs(owner)
100 .enumerate() 100 .enumerate()
101 .flat_map(|(i, attr)| match attr { 101 .flat_map(|(i, attr)| {
102 Either::Left(attr) => Attr::from_src(attr, hygiene, i as u32), 102 let index = AttrId(i as u32);
103 Either::Right(comment) => comment.doc_comment().map(|doc| Attr { 103 match attr {
104 index: i as u32, 104 Either::Left(attr) => Attr::from_src(attr, hygiene, index),
105 input: Some(AttrInput::Literal(SmolStr::new(doc))), 105 Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
106 path: Interned::new(ModPath::from(hir_expand::name!(doc))), 106 id: index,
107 }), 107 input: Some(AttrInput::Literal(SmolStr::new(doc))),
108 path: Interned::new(ModPath::from(hir_expand::name!(doc))),
109 }),
110 }
108 }) 111 })
109 .collect::<Arc<_>>(); 112 .collect::<Arc<_>>();
110 113
@@ -161,7 +164,7 @@ impl RawAttrs {
161 let cfg = parts.next().unwrap(); 164 let cfg = parts.next().unwrap();
162 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; 165 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
163 let cfg = CfgExpr::parse(&cfg); 166 let cfg = CfgExpr::parse(&cfg);
164 let index = attr.index; 167 let index = attr.id;
165 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { 168 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
166 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; 169 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
167 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; 170 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
@@ -215,12 +218,11 @@ impl Attrs {
215 let mut res = ArenaMap::default(); 218 let mut res = ArenaMap::default();
216 219
217 for (id, fld) in src.value.iter() { 220 for (id, fld) in src.value.iter() {
218 let attrs = match fld { 221 let owner: &dyn AttrsOwner = match fld {
219 Either::Left(_tuple) => Attrs::default(), 222 Either::Left(tuple) => tuple,
220 Either::Right(record) => { 223 Either::Right(record) => record,
221 RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate)
222 }
223 }; 224 };
225 let attrs = RawAttrs::from_attrs_owner(db, src.with_value(owner)).filter(db, krate);
224 226
225 res.insert(id, attrs); 227 res.insert(id, attrs);
226 } 228 }
@@ -404,10 +406,14 @@ impl AttrsWithOwner {
404 return AttrSourceMap { attrs }; 406 return AttrSourceMap { attrs };
405 } 407 }
406 AttrDefId::FieldId(id) => { 408 AttrDefId::FieldId(id) => {
407 id.parent.child_source(db).map(|source| match &source[id.local_id] { 409 let map = db.fields_attrs_source_map(id.parent);
408 Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), 410 let file_id = id.parent.file_id(db);
409 Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), 411 let root = db.parse_or_expand(file_id).unwrap();
410 }) 412 let owner = match &map[id.local_id] {
413 Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
414 Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
415 };
416 InFile::new(file_id, owner)
411 } 417 }
412 AttrDefId::AdtId(adt) => match adt { 418 AttrDefId::AdtId(adt) => match adt {
413 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 419 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -415,10 +421,12 @@ impl AttrsWithOwner {
415 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 421 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
416 }, 422 },
417 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 423 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
418 AttrDefId::EnumVariantId(id) => id 424 AttrDefId::EnumVariantId(id) => {
419 .parent 425 let map = db.variants_attrs_source_map(id.parent);
420 .child_source(db) 426 let file_id = id.parent.lookup(db).id.file_id();
421 .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), 427 let root = db.parse_or_expand(file_id).unwrap();
428 InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root)))
429 }
422 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 430 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
423 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 431 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
424 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 432 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -463,7 +471,7 @@ impl AttrsWithOwner {
463 ) -> Option<(Documentation, DocsRangeMap)> { 471 ) -> Option<(Documentation, DocsRangeMap)> {
464 // FIXME: code duplication in `docs` above 472 // FIXME: code duplication in `docs` above
465 let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { 473 let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? {
466 AttrInput::Literal(s) => Some((s, attr.index)), 474 AttrInput::Literal(s) => Some((s, attr.id)),
467 AttrInput::TokenTree(_) => None, 475 AttrInput::TokenTree(_) => None,
468 }); 476 });
469 let indent = docs 477 let indent = docs
@@ -555,8 +563,8 @@ impl AttrSourceMap {
555 /// the attribute represented by `Attr`. 563 /// the attribute represented by `Attr`.
556 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> { 564 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
557 self.attrs 565 self.attrs
558 .get(attr.index as usize) 566 .get(attr.id.0 as usize)
559 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) 567 .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", attr.id))
560 .as_ref() 568 .as_ref()
561 } 569 }
562} 570}
@@ -567,7 +575,7 @@ pub struct DocsRangeMap {
567 // (docstring-line-range, attr_index, attr-string-range) 575 // (docstring-line-range, attr_index, attr-string-range)
568 // a mapping from the text range of a line of the [`Documentation`] to the attribute index and 576 // a mapping from the text range of a line of the [`Documentation`] to the attribute index and
569 // the original (untrimmed) syntax doc line 577 // the original (untrimmed) syntax doc line
570 mapping: Vec<(TextRange, u32, TextRange)>, 578 mapping: Vec<(TextRange, AttrId, TextRange)>,
571} 579}
572 580
573impl DocsRangeMap { 581impl DocsRangeMap {
@@ -580,7 +588,7 @@ impl DocsRangeMap {
580 588
581 let relative_range = range - line_docs_range.start(); 589 let relative_range = range - line_docs_range.start();
582 590
583 let &InFile { file_id, value: ref source } = &self.source[idx as usize]; 591 let &InFile { file_id, value: ref source } = &self.source[idx.0 as usize];
584 match source { 592 match source {
585 Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here 593 Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here
586 // as well as for whats done in syntax highlight doc injection 594 // as well as for whats done in syntax highlight doc injection
@@ -601,7 +609,7 @@ impl DocsRangeMap {
601 609
602#[derive(Debug, Clone, PartialEq, Eq)] 610#[derive(Debug, Clone, PartialEq, Eq)]
603pub struct Attr { 611pub struct Attr {
604 index: u32, 612 pub(crate) id: AttrId,
605 pub(crate) path: Interned<ModPath>, 613 pub(crate) path: Interned<ModPath>,
606 pub(crate) input: Option<AttrInput>, 614 pub(crate) input: Option<AttrInput>,
607} 615}
@@ -615,7 +623,7 @@ pub enum AttrInput {
615} 623}
616 624
617impl Attr { 625impl Attr {
618 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { 626 fn from_src(ast: ast::Attr, hygiene: &Hygiene, id: AttrId) -> Option<Attr> {
619 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?); 627 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?);
620 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { 628 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
621 let value = match lit.kind() { 629 let value = match lit.kind() {
@@ -628,7 +636,7 @@ impl Attr {
628 } else { 636 } else {
629 None 637 None
630 }; 638 };
631 Some(Attr { index, path, input }) 639 Some(Attr { id, path, input })
632 } 640 }
633 641
634 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths 642 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
@@ -743,7 +751,38 @@ fn collect_attrs(
743 .chain(inner_docs.into_iter().flatten()) 751 .chain(inner_docs.into_iter().flatten())
744 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text))); 752 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
745 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved 753 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
746 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); 754 docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).map(|(_, attr)| attr)
755}
756
757pub(crate) fn variants_attrs_source_map(
758 db: &dyn DefDatabase,
759 def: EnumId,
760) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
761 let mut res = ArenaMap::default();
762 let child_source = def.child_source(db);
763
764 for (idx, variant) in child_source.value.iter() {
765 res.insert(idx, AstPtr::new(variant));
766 }
767
768 Arc::new(res)
769}
770
771pub(crate) fn fields_attrs_source_map(
772 db: &dyn DefDatabase,
773 def: VariantId,
774) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> {
775 let mut res = ArenaMap::default();
776 let child_source = def.child_source(db);
777
778 for (idx, variant) in child_source.value.iter() {
779 res.insert(
780 idx,
781 variant
782 .as_ref()
783 .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))),
784 );
785 }
747 786
748 attrs.into_iter().map(|(_, attr)| attr) 787 Arc::new(res)
749} 788}
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 63e89a1f4..ed07d6928 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -30,6 +30,7 @@ use crate::{
30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, 30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
31 Statement, 31 Statement,
32 }, 32 },
33 intern::Interned,
33 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
34 path::{GenericArgs, Path}, 35 path::{GenericArgs, Path},
35 type_ref::{Mutability, Rawness, TypeRef}, 36 type_ref::{Mutability, Rawness, TypeRef},
@@ -322,8 +323,10 @@ impl ExprCollector<'_> {
322 Vec::new() 323 Vec::new()
323 }; 324 };
324 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
325 let generic_args = 326 let generic_args = e
326 e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 327 .generic_arg_list()
328 .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
329 .map(Box::new);
327 self.alloc_expr( 330 self.alloc_expr(
328 Expr::MethodCall { receiver, method_name, args, generic_args }, 331 Expr::MethodCall { receiver, method_name, args, generic_args },
329 syntax_ptr, 332 syntax_ptr,
@@ -385,7 +388,7 @@ impl ExprCollector<'_> {
385 self.alloc_expr(Expr::Yield { expr }, syntax_ptr) 388 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
386 } 389 }
387 ast::Expr::RecordExpr(e) => { 390 ast::Expr::RecordExpr(e) => {
388 let path = e.path().and_then(|path| self.expander.parse_path(path)); 391 let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
389 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 392 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
390 let fields = nfl 393 let fields = nfl
391 .fields() 394 .fields()
@@ -430,7 +433,7 @@ impl ExprCollector<'_> {
430 } 433 }
431 ast::Expr::CastExpr(e) => { 434 ast::Expr::CastExpr(e) => {
432 let expr = self.collect_expr_opt(e.expr()); 435 let expr = self.collect_expr_opt(e.expr());
433 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); 436 let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
434 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 437 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
435 } 438 }
436 ast::Expr::RefExpr(e) => { 439 ast::Expr::RefExpr(e) => {
@@ -464,13 +467,16 @@ impl ExprCollector<'_> {
464 if let Some(pl) = e.param_list() { 467 if let Some(pl) = e.param_list() {
465 for param in pl.params() { 468 for param in pl.params() {
466 let pat = self.collect_pat_opt(param.pat()); 469 let pat = self.collect_pat_opt(param.pat());
467 let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 470 let type_ref =
471 param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
468 args.push(pat); 472 args.push(pat);
469 arg_types.push(type_ref); 473 arg_types.push(type_ref);
470 } 474 }
471 } 475 }
472 let ret_type = 476 let ret_type = e
473 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); 477 .ret_type()
478 .and_then(|r| r.ty())
479 .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
474 let body = self.collect_expr_opt(e.body()); 480 let body = self.collect_expr_opt(e.body());
475 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 481 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
476 } 482 }
@@ -525,8 +531,9 @@ impl ExprCollector<'_> {
525 } 531 }
526 } 532 }
527 ast::Expr::MacroCall(e) => { 533 ast::Expr::MacroCall(e) => {
534 let macro_ptr = AstPtr::new(&e);
528 let mut ids = vec![]; 535 let mut ids = vec![];
529 self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| { 536 self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
530 ids.push(match expansion { 537 ids.push(match expansion {
531 Some(it) => this.collect_expr(it), 538 Some(it) => this.collect_expr(it),
532 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 539 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -549,7 +556,7 @@ impl ExprCollector<'_> {
549 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>( 556 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
550 &mut self, 557 &mut self,
551 e: ast::MacroCall, 558 e: ast::MacroCall,
552 syntax_ptr: AstPtr<ast::Expr>, 559 syntax_ptr: AstPtr<ast::MacroCall>,
553 is_error_recoverable: bool, 560 is_error_recoverable: bool,
554 mut collector: F, 561 mut collector: F,
555 ) { 562 ) {
@@ -625,7 +632,8 @@ impl ExprCollector<'_> {
625 return; 632 return;
626 } 633 }
627 let pat = self.collect_pat_opt(stmt.pat()); 634 let pat = self.collect_pat_opt(stmt.pat());
628 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 635 let type_ref =
636 stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
629 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 637 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
630 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer }); 638 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
631 } 639 }
@@ -636,10 +644,14 @@ impl ExprCollector<'_> {
636 644
637 // Note that macro could be expended to multiple statements 645 // Note that macro could be expended to multiple statements
638 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 646 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
647 let macro_ptr = AstPtr::new(&m);
639 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 648 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
640 649
641 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { 650 self.collect_macro_call(
642 match expansion { 651 m,
652 macro_ptr,
653 false,
654 |this, expansion| match expansion {
643 Some(expansion) => { 655 Some(expansion) => {
644 let statements: ast::MacroStmts = expansion; 656 let statements: ast::MacroStmts = expansion;
645 657
@@ -653,8 +665,8 @@ impl ExprCollector<'_> {
653 let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); 665 let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
654 this.statements_in_scope.push(Statement::Expr(expr)); 666 this.statements_in_scope.push(Statement::Expr(expr));
655 } 667 }
656 } 668 },
657 }); 669 );
658 } else { 670 } else {
659 let expr = self.collect_expr_opt(stmt.expr()); 671 let expr = self.collect_expr_opt(stmt.expr());
660 self.statements_in_scope.push(Statement::Expr(expr)); 672 self.statements_in_scope.push(Statement::Expr(expr));
@@ -755,7 +767,7 @@ impl ExprCollector<'_> {
755 } 767 }
756 } 768 }
757 ast::Pat::TupleStructPat(p) => { 769 ast::Pat::TupleStructPat(p) => {
758 let path = p.path().and_then(|path| self.expander.parse_path(path)); 770 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
759 let (args, ellipsis) = self.collect_tuple_pat(p.fields()); 771 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
760 Pat::TupleStruct { path, args, ellipsis } 772 Pat::TupleStruct { path, args, ellipsis }
761 } 773 }
@@ -765,7 +777,7 @@ impl ExprCollector<'_> {
765 Pat::Ref { pat, mutability } 777 Pat::Ref { pat, mutability }
766 } 778 }
767 ast::Pat::PathPat(p) => { 779 ast::Pat::PathPat(p) => {
768 let path = p.path().and_then(|path| self.expander.parse_path(path)); 780 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
769 path.map(Pat::Path).unwrap_or(Pat::Missing) 781 path.map(Pat::Path).unwrap_or(Pat::Missing)
770 } 782 }
771 ast::Pat::OrPat(p) => { 783 ast::Pat::OrPat(p) => {
@@ -779,7 +791,7 @@ impl ExprCollector<'_> {
779 } 791 }
780 ast::Pat::WildcardPat(_) => Pat::Wild, 792 ast::Pat::WildcardPat(_) => Pat::Wild,
781 ast::Pat::RecordPat(p) => { 793 ast::Pat::RecordPat(p) => {
782 let path = p.path().and_then(|path| self.expander.parse_path(path)); 794 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
783 let args: Vec<_> = p 795 let args: Vec<_> = p
784 .record_pat_field_list() 796 .record_pat_field_list()
785 .expect("every struct should have a field list") 797 .expect("every struct should have a field list")
@@ -841,8 +853,23 @@ impl ExprCollector<'_> {
841 Pat::Missing 853 Pat::Missing
842 } 854 }
843 } 855 }
856 ast::Pat::MacroPat(mac) => match mac.macro_call() {
857 Some(call) => {
858 let macro_ptr = AstPtr::new(&call);
859 let mut pat = None;
860 self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
861 pat = Some(this.collect_pat_opt(expanded_pat));
862 });
863
864 match pat {
865 Some(pat) => return pat,
866 None => Pat::Missing,
867 }
868 }
869 None => Pat::Missing,
870 },
844 // FIXME: implement 871 // FIXME: implement
845 ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, 872 ast::Pat::RangePat(_) => Pat::Missing,
846 }; 873 };
847 let ptr = AstPtr::new(&pat); 874 let ptr = AstPtr::new(&pat);
848 self.alloc_pat(pattern, Either::Left(ptr)) 875 self.alloc_pat(pattern, Either::Left(ptr))
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index faa133297..c1d3e998f 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -143,7 +143,7 @@ fn f() {
143 //^^^^^^^^^^^^^ could not convert tokens 143 //^^^^^^^^^^^^^ could not convert tokens
144 144
145 env!("OUT_DIR"); 145 env!("OUT_DIR");
146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix 146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix
147 147
148 compile_error!("compile_error works"); 148 compile_error!("compile_error works");
149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works 149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index f40a7f80d..f2e809ca9 100644
--- a/crates/hir_def/src/child_by_source.rs
+++ b/crates/hir_def/src/child_by_source.rs
@@ -80,6 +80,10 @@ impl ChildBySource for ModuleId {
80impl ChildBySource for ItemScope { 80impl ChildBySource for ItemScope {
81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { 81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
82 self.declarations().for_each(|item| add_module_def(db, res, item)); 82 self.declarations().for_each(|item| add_module_def(db, res, item));
83 self.unnamed_consts().for_each(|konst| {
84 let src = konst.lookup(db).source(db);
85 res[keys::CONST].insert(src, konst);
86 });
83 self.impls().for_each(|imp| add_impl(db, res, imp)); 87 self.impls().for_each(|imp| add_impl(db, res, imp));
84 88
85 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { 89 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 9b7a213a1..7eadc8e0d 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -2,9 +2,10 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use base_db::{salsa, CrateId, SourceDatabase, Upcast}; 4use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5use either::Either;
5use hir_expand::{db::AstDatabase, HirFileId}; 6use hir_expand::{db::AstDatabase, HirFileId};
6use la_arena::ArenaMap; 7use la_arena::ArenaMap;
7use syntax::SmolStr; 8use syntax::{ast, AstPtr, SmolStr};
8 9
9use crate::{ 10use crate::{
10 adt::{EnumData, StructData}, 11 adt::{EnumData, StructData},
@@ -122,6 +123,18 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
122 #[salsa::invoke(Attrs::fields_attrs_query)] 123 #[salsa::invoke(Attrs::fields_attrs_query)]
123 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; 124 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
124 125
126 #[salsa::invoke(crate::attr::variants_attrs_source_map)]
127 fn variants_attrs_source_map(
128 &self,
129 def: EnumId,
130 ) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>;
131
132 #[salsa::invoke(crate::attr::fields_attrs_source_map)]
133 fn fields_attrs_source_map(
134 &self,
135 def: VariantId,
136 ) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>>;
137
125 #[salsa::invoke(AttrsWithOwner::attrs_query)] 138 #[salsa::invoke(AttrsWithOwner::attrs_query)]
126 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; 139 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner;
127 140
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 6c7376fad..b4ad984bd 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -18,6 +18,7 @@ use syntax::ast::RangeOp;
18 18
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, 20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
21 intern::Interned,
21 path::{GenericArgs, Path}, 22 path::{GenericArgs, Path},
22 type_ref::{Mutability, Rawness, TypeRef}, 23 type_ref::{Mutability, Rawness, TypeRef},
23 BlockId, 24 BlockId,
@@ -86,7 +87,7 @@ pub enum Expr {
86 receiver: ExprId, 87 receiver: ExprId,
87 method_name: Name, 88 method_name: Name,
88 args: Vec<ExprId>, 89 args: Vec<ExprId>,
89 generic_args: Option<GenericArgs>, 90 generic_args: Option<Box<GenericArgs>>,
90 }, 91 },
91 Match { 92 Match {
92 expr: ExprId, 93 expr: ExprId,
@@ -106,7 +107,7 @@ pub enum Expr {
106 expr: Option<ExprId>, 107 expr: Option<ExprId>,
107 }, 108 },
108 RecordLit { 109 RecordLit {
109 path: Option<Path>, 110 path: Option<Box<Path>>,
110 fields: Vec<RecordLitField>, 111 fields: Vec<RecordLitField>,
111 spread: Option<ExprId>, 112 spread: Option<ExprId>,
112 }, 113 },
@@ -131,7 +132,7 @@ pub enum Expr {
131 }, 132 },
132 Cast { 133 Cast {
133 expr: ExprId, 134 expr: ExprId,
134 type_ref: TypeRef, 135 type_ref: Interned<TypeRef>,
135 }, 136 },
136 Ref { 137 Ref {
137 expr: ExprId, 138 expr: ExprId,
@@ -161,8 +162,8 @@ pub enum Expr {
161 }, 162 },
162 Lambda { 163 Lambda {
163 args: Vec<PatId>, 164 args: Vec<PatId>,
164 arg_types: Vec<Option<TypeRef>>, 165 arg_types: Vec<Option<Interned<TypeRef>>>,
165 ret_type: Option<TypeRef>, 166 ret_type: Option<Interned<TypeRef>>,
166 body: ExprId, 167 body: ExprId,
167 }, 168 },
168 Tuple { 169 Tuple {
@@ -240,7 +241,7 @@ pub struct RecordLitField {
240 241
241#[derive(Debug, Clone, Eq, PartialEq)] 242#[derive(Debug, Clone, Eq, PartialEq)]
242pub enum Statement { 243pub enum Statement {
243 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> }, 244 Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> },
244 Expr(ExprId), 245 Expr(ExprId),
245} 246}
246 247
@@ -412,13 +413,13 @@ pub enum Pat {
412 Wild, 413 Wild,
413 Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, 414 Tuple { args: Vec<PatId>, ellipsis: Option<usize> },
414 Or(Vec<PatId>), 415 Or(Vec<PatId>),
415 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, 416 Record { path: Option<Box<Path>>, args: Vec<RecordFieldPat>, ellipsis: bool },
416 Range { start: ExprId, end: ExprId }, 417 Range { start: ExprId, end: ExprId },
417 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, 418 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
418 Path(Path), 419 Path(Box<Path>),
419 Lit(ExprId), 420 Lit(ExprId),
420 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, 421 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
421 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, 422 TupleStruct { path: Option<Box<Path>>, args: Vec<PatId>, ellipsis: Option<usize> },
422 Ref { pat: PatId, mutability: Mutability }, 423 Ref { pat: PatId, mutability: Mutability },
423 Box { inner: PatId }, 424 Box { inner: PatId },
424 ConstBlock(ExprId), 425 ConstBlock(ExprId),
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index a8ee5eeac..9014468ea 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -11,7 +11,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
11use stdx::format_to; 11use stdx::format_to;
12 12
13use crate::{ 13use crate::{
14 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, 14 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId,
15 LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, 15 LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId,
16}; 16};
17 17
@@ -37,6 +37,7 @@ pub struct ItemScope {
37 37
38 defs: Vec<ModuleDefId>, 38 defs: Vec<ModuleDefId>,
39 impls: Vec<ImplId>, 39 impls: Vec<ImplId>,
40 unnamed_consts: Vec<ConstId>,
40 /// Traits imported via `use Trait as _;`. 41 /// Traits imported via `use Trait as _;`.
41 unnamed_trait_imports: FxHashMap<TraitId, Visibility>, 42 unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
42 /// Macros visible in current module in legacy textual scope 43 /// Macros visible in current module in legacy textual scope
@@ -106,6 +107,10 @@ impl ItemScope {
106 .map(|(_, v)| v) 107 .map(|(_, v)| v)
107 } 108 }
108 109
110 pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
111 self.unnamed_consts.iter().copied()
112 }
113
109 /// Iterate over all module scoped macros 114 /// Iterate over all module scoped macros
110 pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 115 pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
111 self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) 116 self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
@@ -156,6 +161,10 @@ impl ItemScope {
156 self.impls.push(imp) 161 self.impls.push(imp)
157 } 162 }
158 163
164 pub(crate) fn define_unnamed_const(&mut self, konst: ConstId) {
165 self.unnamed_consts.push(konst);
166 }
167
159 pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) { 168 pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
160 self.legacy_macros.insert(name, mac); 169 self.legacy_macros.insert(name, mac);
161 } 170 }
@@ -295,6 +304,7 @@ impl ItemScope {
295 unresolved, 304 unresolved,
296 defs, 305 defs,
297 impls, 306 impls,
307 unnamed_consts,
298 unnamed_trait_imports, 308 unnamed_trait_imports,
299 legacy_macros, 309 legacy_macros,
300 } = self; 310 } = self;
@@ -304,6 +314,7 @@ impl ItemScope {
304 unresolved.shrink_to_fit(); 314 unresolved.shrink_to_fit();
305 defs.shrink_to_fit(); 315 defs.shrink_to_fit();
306 impls.shrink_to_fit(); 316 impls.shrink_to_fit();
317 unnamed_consts.shrink_to_fit();
307 unnamed_trait_imports.shrink_to_fit(); 318 unnamed_trait_imports.shrink_to_fit();
308 legacy_macros.shrink_to_fit(); 319 legacy_macros.shrink_to_fit();
309 } 320 }
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 240662486..94e08f835 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -99,6 +99,11 @@ impl ItemTree {
99 // items. 99 // items.
100 ctx.lower_macro_stmts(stmts) 100 ctx.lower_macro_stmts(stmts)
101 }, 101 },
102 ast::Pat(_pat) => {
103 // FIXME: This occurs because macros in pattern position are treated as inner
104 // items and expanded during block DefMap computation
105 return Default::default();
106 },
102 ast::Expr(e) => { 107 ast::Expr(e) => {
103 // Macros can expand to expressions. We return an empty item tree in this case, but 108 // Macros can expand to expressions. We return an empty item tree in this case, but
104 // still need to collect inner items. 109 // still need to collect inner items.
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index c5629af24..45b099cf3 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -189,7 +189,7 @@ impl Ctx {
189 block_stack.push(self.source_ast_id_map.ast_id(&block)); 189 block_stack.push(self.source_ast_id_map.ast_id(&block));
190 }, 190 },
191 ast::Item(item) => { 191 ast::Item(item) => {
192 // FIXME: This triggers for macro calls in expression position 192 // FIXME: This triggers for macro calls in expression/pattern/type position
193 let mod_items = self.lower_mod_item(&item, true); 193 let mod_items = self.lower_mod_item(&item, true);
194 let current_block = block_stack.last(); 194 let current_block = block_stack.last();
195 if let (Some(mod_items), Some(block)) = (mod_items, current_block) { 195 if let (Some(mod_items), Some(block)) = (mod_items, current_block) {
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index be9a5e1a0..d69116d51 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -56,12 +56,13 @@ use std::{
56 sync::Arc, 56 sync::Arc,
57}; 57};
58 58
59use adt::VariantData;
59use base_db::{impl_intern_key, salsa, CrateId}; 60use base_db::{impl_intern_key, salsa, CrateId};
60use hir_expand::{ 61use hir_expand::{
61 ast_id_map::FileAstId, 62 ast_id_map::FileAstId,
62 eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, 63 eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
63 hygiene::Hygiene, 64 hygiene::Hygiene,
64 AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 65 AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
65}; 66};
66use la_arena::Idx; 67use la_arena::Idx;
67use nameres::DefMap; 68use nameres::DefMap;
@@ -442,6 +443,26 @@ pub enum VariantId {
442} 443}
443impl_from!(EnumVariantId, StructId, UnionId for VariantId); 444impl_from!(EnumVariantId, StructId, UnionId for VariantId);
444 445
446impl VariantId {
447 pub fn variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData> {
448 match self {
449 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
450 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
451 VariantId::EnumVariantId(it) => {
452 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
453 }
454 }
455 }
456
457 pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
458 match self {
459 VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
460 VariantId::StructId(it) => it.lookup(db).id.file_id(),
461 VariantId::UnionId(it) => it.lookup(db).id.file_id(),
462 }
463 }
464}
465
445trait Intern { 466trait Intern {
446 type ID; 467 type ID;
447 fn intern(self, db: &dyn db::DefDatabase) -> Self::ID; 468 fn intern(self, db: &dyn db::DefDatabase) -> Self::ID;
@@ -669,13 +690,16 @@ fn macro_call_as_call_id(
669 ) 690 )
670 .map(MacroCallId::from) 691 .map(MacroCallId::from)
671 } else { 692 } else {
672 Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into()) 693 Ok(def
694 .as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id })
695 .into())
673 }; 696 };
674 Ok(res) 697 Ok(res)
675} 698}
676 699
677fn derive_macro_as_call_id( 700fn derive_macro_as_call_id(
678 item_attr: &AstIdWithPath<ast::Item>, 701 item_attr: &AstIdWithPath<ast::Item>,
702 derive_attr: AttrId,
679 db: &dyn db::DefDatabase, 703 db: &dyn db::DefDatabase,
680 krate: CrateId, 704 krate: CrateId,
681 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 705 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
@@ -686,7 +710,11 @@ fn derive_macro_as_call_id(
686 .as_lazy_macro( 710 .as_lazy_macro(
687 db.upcast(), 711 db.upcast(),
688 krate, 712 krate,
689 MacroCallKind::Derive(item_attr.ast_id, last_segment.to_string()), 713 MacroCallKind::Derive {
714 ast_id: item_attr.ast_id,
715 derive_name: last_segment.to_string(),
716 derive_attr,
717 },
690 ) 718 )
691 .into(); 719 .into();
692 Ok(res) 720 Ok(res)
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 7dd68219f..9e181751c 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -613,12 +613,12 @@ mod diagnostics {
613 DiagnosticKind::UnresolvedProcMacro { ast } => { 613 DiagnosticKind::UnresolvedProcMacro { ast } => {
614 let mut precise_location = None; 614 let mut precise_location = None;
615 let (file, ast, name) = match ast { 615 let (file, ast, name) = match ast {
616 MacroCallKind::FnLike(ast) => { 616 MacroCallKind::FnLike { ast_id } => {
617 let node = ast.to_node(db.upcast()); 617 let node = ast_id.to_node(db.upcast());
618 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) 618 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
619 } 619 }
620 MacroCallKind::Derive(ast, name) => { 620 MacroCallKind::Derive { ast_id, derive_name, .. } => {
621 let node = ast.to_node(db.upcast()); 621 let node = ast_id.to_node(db.upcast());
622 622
623 // Compute the precise location of the macro name's token in the derive 623 // Compute the precise location of the macro name's token in the derive
624 // list. 624 // list.
@@ -639,7 +639,7 @@ mod diagnostics {
639 }); 639 });
640 for token in tokens { 640 for token in tokens {
641 if token.kind() == SyntaxKind::IDENT 641 if token.kind() == SyntaxKind::IDENT
642 && token.text() == name.as_str() 642 && token.text() == derive_name.as_str()
643 { 643 {
644 precise_location = Some(token.text_range()); 644 precise_location = Some(token.text_range());
645 break 'outer; 645 break 'outer;
@@ -648,9 +648,9 @@ mod diagnostics {
648 } 648 }
649 649
650 ( 650 (
651 ast.file_id, 651 ast_id.file_id,
652 SyntaxNodePtr::from(AstPtr::new(&node)), 652 SyntaxNodePtr::from(AstPtr::new(&node)),
653 Some(name.clone()), 653 Some(derive_name.clone()),
654 ) 654 )
655 } 655 }
656 }; 656 };
@@ -669,13 +669,13 @@ mod diagnostics {
669 669
670 DiagnosticKind::MacroError { ast, message } => { 670 DiagnosticKind::MacroError { ast, message } => {
671 let (file, ast) = match ast { 671 let (file, ast) = match ast {
672 MacroCallKind::FnLike(ast) => { 672 MacroCallKind::FnLike { ast_id, .. } => {
673 let node = ast.to_node(db.upcast()); 673 let node = ast_id.to_node(db.upcast());
674 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) 674 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
675 } 675 }
676 MacroCallKind::Derive(ast, _) => { 676 MacroCallKind::Derive { ast_id, .. } => {
677 let node = ast.to_node(db.upcast()); 677 let node = ast_id.to_node(db.upcast());
678 (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) 678 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
679 } 679 }
680 }; 680 };
681 sink.push(MacroError { file, node: ast, message: message.clone() }); 681 sink.push(MacroError { file, node: ast, message: message.clone() });
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index f42f92702..fb4ddff5e 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -216,7 +216,7 @@ struct MacroDirective {
216#[derive(Clone, Debug, Eq, PartialEq)] 216#[derive(Clone, Debug, Eq, PartialEq)]
217enum MacroDirectiveKind { 217enum MacroDirectiveKind {
218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> }, 218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> },
219 Derive { ast_id: AstIdWithPath<ast::Item> }, 219 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
220} 220}
221 221
222struct DefData<'a> { 222struct DefData<'a> {
@@ -478,7 +478,7 @@ impl DefCollector<'_> {
478 self.def_map.edition, 478 self.def_map.edition,
479 ); 479 );
480 480
481 let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name); 481 let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
482 482
483 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 483 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
484 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); 484 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
@@ -534,6 +534,7 @@ impl DefCollector<'_> {
534 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 534 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
535 if import.is_extern_crate { 535 if import.is_extern_crate {
536 let res = self.def_map.resolve_name_in_extern_prelude( 536 let res = self.def_map.resolve_name_in_extern_prelude(
537 self.db,
537 &import 538 &import
538 .path 539 .path
539 .as_ident() 540 .as_ident()
@@ -831,12 +832,16 @@ impl DefCollector<'_> {
831 Err(UnresolvedMacro) | Ok(Err(_)) => {} 832 Err(UnresolvedMacro) | Ok(Err(_)) => {}
832 } 833 }
833 } 834 }
834 MacroDirectiveKind::Derive { ast_id } => { 835 MacroDirectiveKind::Derive { ast_id, derive_attr } => {
835 match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| { 836 match derive_macro_as_call_id(
836 self.resolve_derive_macro(directive.module_id, &path) 837 ast_id,
837 }) { 838 *derive_attr,
839 self.db,
840 self.def_map.krate,
841 |path| self.resolve_derive_macro(directive.module_id, &path),
842 ) {
838 Ok(call_id) => { 843 Ok(call_id) => {
839 resolved.push((directive.module_id, call_id, 0)); 844 resolved.push((directive.module_id, call_id, directive.depth));
840 res = ReachedFixedPoint::No; 845 res = ReachedFixedPoint::No;
841 return false; 846 return false;
842 } 847 }
@@ -1163,19 +1168,27 @@ impl ModCollector<'_, '_> {
1163 } 1168 }
1164 ModItem::Const(id) => { 1169 ModItem::Const(id) => {
1165 let it = &self.item_tree[id]; 1170 let it = &self.item_tree[id];
1166 1171 let const_id = ConstLoc {
1167 if let Some(name) = &it.name { 1172 container: module.into(),
1168 def = Some(DefData { 1173 id: ItemTreeId::new(self.file_id, id),
1169 id: ConstLoc { 1174 }
1170 container: module.into(), 1175 .intern(self.def_collector.db);
1171 id: ItemTreeId::new(self.file_id, id), 1176
1172 } 1177 match &it.name {
1173 .intern(self.def_collector.db) 1178 Some(name) => {
1174 .into(), 1179 def = Some(DefData {
1175 name, 1180 id: const_id.into(),
1176 visibility: &self.item_tree[it.visibility], 1181 name,
1177 has_constructor: false, 1182 visibility: &self.item_tree[it.visibility],
1178 }); 1183 has_constructor: false,
1184 });
1185 }
1186 None => {
1187 // const _: T = ...;
1188 self.def_collector.def_map.modules[self.module_id]
1189 .scope
1190 .define_unnamed_const(const_id);
1191 }
1179 } 1192 }
1180 } 1193 }
1181 ModItem::Static(id) => { 1194 ModItem::Static(id) => {
@@ -1360,7 +1373,7 @@ impl ModCollector<'_, '_> {
1360 self.def_collector.unexpanded_macros.push(MacroDirective { 1373 self.def_collector.unexpanded_macros.push(MacroDirective {
1361 module_id: self.module_id, 1374 module_id: self.module_id,
1362 depth: self.macro_depth + 1, 1375 depth: self.macro_depth + 1,
1363 kind: MacroDirectiveKind::Derive { ast_id }, 1376 kind: MacroDirectiveKind::Derive { ast_id, derive_attr: derive.id },
1364 }); 1377 });
1365 } 1378 }
1366 } 1379 }
@@ -1512,7 +1525,7 @@ impl ModCollector<'_, '_> {
1512 // Built-in macro failed eager expansion. 1525 // Built-in macro failed eager expansion.
1513 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( 1526 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1514 self.module_id, 1527 self.module_id,
1515 MacroCallKind::FnLike(ast_id.ast_id), 1528 MacroCallKind::FnLike { ast_id: ast_id.ast_id },
1516 error.unwrap().to_string(), 1529 error.unwrap().to_string(),
1517 )); 1530 ));
1518 return; 1531 return;
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index 60471937c..ccc9f22eb 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -60,12 +60,26 @@ impl ResolvePathResult {
60} 60}
61 61
62impl DefMap { 62impl DefMap {
63 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 63 pub(super) fn resolve_name_in_extern_prelude(
64 &self,
65 db: &dyn DefDatabase,
66 name: &Name,
67 ) -> PerNs {
64 if name == &name!(self) { 68 if name == &name!(self) {
65 cov_mark::hit!(extern_crate_self_as); 69 cov_mark::hit!(extern_crate_self_as);
66 return PerNs::types(self.module_id(self.root).into(), Visibility::Public); 70 return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
67 } 71 }
68 self.extern_prelude 72
73 let arc;
74 let root = match self.block {
75 Some(_) => {
76 arc = self.crate_root(db).def_map(db);
77 &*arc
78 }
79 None => self,
80 };
81
82 root.extern_prelude
69 .get(name) 83 .get(name)
70 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) 84 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
71 } 85 }
@@ -191,7 +205,7 @@ impl DefMap {
191 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 205 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
192 }; 206 };
193 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 207 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
194 self.resolve_name_in_crate_root_or_extern_prelude(&segment) 208 self.resolve_name_in_crate_root_or_extern_prelude(db, &segment)
195 } 209 }
196 PathKind::Plain => { 210 PathKind::Plain => {
197 let (_, segment) = match segments.next() { 211 let (_, segment) = match segments.next() {
@@ -384,24 +398,31 @@ impl DefMap {
384 } 398 }
385 } 399 }
386 }; 400 };
387 // Give precedence to names in outer `DefMap`s over the extern prelude; only check prelude 401 let from_extern_prelude = self
388 // from the crate DefMap. 402 .extern_prelude
389 let from_extern_prelude = match self.block { 403 .get(name)
390 Some(_) => PerNs::none(), 404 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public));
391 None => self
392 .extern_prelude
393 .get(name)
394 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)),
395 };
396 405
397 let from_prelude = self.resolve_in_prelude(db, name); 406 let from_prelude = self.resolve_in_prelude(db, name);
398 407
399 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) 408 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude)
400 } 409 }
401 410
402 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { 411 fn resolve_name_in_crate_root_or_extern_prelude(
403 let from_crate_root = self[self.root].scope.get(name); 412 &self,
404 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 413 db: &dyn DefDatabase,
414 name: &Name,
415 ) -> PerNs {
416 let arc;
417 let crate_def_map = match self.block {
418 Some(_) => {
419 arc = self.crate_root(db).def_map(db);
420 &arc
421 }
422 None => self,
423 };
424 let from_crate_root = crate_def_map[crate_def_map.root].scope.get(name);
425 let from_extern_prelude = self.resolve_name_in_extern_prelude(db, name);
405 426
406 from_crate_root.or(from_extern_prelude) 427 from_crate_root.or(from_extern_prelude)
407 } 428 }
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index fefdadb22..1ac88fc89 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -233,7 +233,7 @@ fn good_out_dir_diagnostic() {
233 macro_rules! concat { () => {} } 233 macro_rules! concat { () => {} }
234 234
235 include!(concat!(env!("OUT_DIR"), "/out.rs")); 235 include!(concat!(env!("OUT_DIR"), "/out.rs"));
236 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix 236 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix
237 "#, 237 "#,
238 ); 238 );
239} 239}
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index f9c8328f0..b528ff8ba 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -289,6 +289,12 @@ impl From<Name> for Path {
289 } 289 }
290} 290}
291 291
292impl From<Name> for Box<Path> {
293 fn from(name: Name) -> Box<Path> {
294 Box::new(Path::from(name))
295 }
296}
297
292impl From<Name> for ModPath { 298impl From<Name> for ModPath {
293 fn from(name: Name) -> ModPath { 299 fn from(name: Name) -> ModPath {
294 ModPath::from_segments(PathKind::Plain, iter::once(name)) 300 ModPath::from_segments(PathKind::Plain, iter::once(name))