diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 105 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 63 | ||||
-rw-r--r-- | crates/hir_def/src/body/tests.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/child_by_source.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 15 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 19 | ||||
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 13 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 5 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 34 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 28 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 59 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 51 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 6 |
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::{ | |||
9 | use base_db::CrateId; | 9 | use base_db::CrateId; |
10 | use cfg::{CfgExpr, CfgOptions}; | 10 | use cfg::{CfgExpr, CfgOptions}; |
11 | use either::Either; | 11 | use either::Either; |
12 | use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; | 12 | use hir_expand::{hygiene::Hygiene, name::AsName, AstId, AttrId, InFile}; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use la_arena::ArenaMap; | 14 | use la_arena::ArenaMap; |
15 | use mbe::ast_to_token_tree; | 15 | use mbe::ast_to_token_tree; |
16 | use smallvec::{smallvec, SmallVec}; | 16 | use smallvec::{smallvec, SmallVec}; |
17 | use syntax::{ | 17 | use 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 | }; |
21 | use tt::Subtree; | 21 | use 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 | ||
573 | impl DocsRangeMap { | 581 | impl 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)] |
603 | pub struct Attr { | 611 | pub 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 | ||
617 | impl Attr { | 625 | impl 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 | |||
757 | pub(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 | |||
771 | pub(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 { | |||
80 | impl ChildBySource for ItemScope { | 80 | impl 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 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | 4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; |
5 | use either::Either; | ||
5 | use hir_expand::{db::AstDatabase, HirFileId}; | 6 | use hir_expand::{db::AstDatabase, HirFileId}; |
6 | use la_arena::ArenaMap; | 7 | use la_arena::ArenaMap; |
7 | use syntax::SmolStr; | 8 | use syntax::{ast, AstPtr, SmolStr}; |
8 | 9 | ||
9 | use crate::{ | 10 | use 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 | ||
19 | use crate::{ | 19 | use 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)] |
242 | pub enum Statement { | 243 | pub 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}; | |||
11 | use stdx::format_to; | 11 | use stdx::format_to; |
12 | 12 | ||
13 | use crate::{ | 13 | use 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 | ||
59 | use adt::VariantData; | ||
59 | use base_db::{impl_intern_key, salsa, CrateId}; | 60 | use base_db::{impl_intern_key, salsa, CrateId}; |
60 | use hir_expand::{ | 61 | use 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 | }; |
66 | use la_arena::Idx; | 67 | use la_arena::Idx; |
67 | use nameres::DefMap; | 68 | use nameres::DefMap; |
@@ -442,6 +443,26 @@ pub enum VariantId { | |||
442 | } | 443 | } |
443 | impl_from!(EnumVariantId, StructId, UnionId for VariantId); | 444 | impl_from!(EnumVariantId, StructId, UnionId for VariantId); |
444 | 445 | ||
446 | impl 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 | |||
445 | trait Intern { | 466 | trait 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 | ||
677 | fn derive_macro_as_call_id( | 700 | fn 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 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -216,7 +216,7 @@ struct MacroDirective { | |||
216 | #[derive(Clone, Debug, Eq, PartialEq)] | 216 | #[derive(Clone, Debug, Eq, PartialEq)] |
217 | enum MacroDirectiveKind { | 217 | enum 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 | ||
222 | struct DefData<'a> { | 222 | struct 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 | ||
62 | impl DefMap { | 62 | impl 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 | ||
292 | impl From<Name> for Box<Path> { | ||
293 | fn from(name: Name) -> Box<Path> { | ||
294 | Box::new(Path::from(name)) | ||
295 | } | ||
296 | } | ||
297 | |||
292 | impl From<Name> for ModPath { | 298 | impl 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)) |