diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 144 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 34 | ||||
-rw-r--r-- | crates/hir_def/src/body/scope.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 8 | ||||
-rw-r--r-- | crates/hir_def/src/find_path.rs | 13 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 14 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 27 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 16 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/incremental.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/type_ref.rs | 73 |
14 files changed, 256 insertions, 93 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index a2479016e..aadd4e44a 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -9,7 +9,7 @@ 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, AttrId, InFile}; | 12 | use hir_expand::{hygiene::Hygiene, name::AsName, AstId, 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; |
@@ -101,17 +101,13 @@ impl RawAttrs { | |||
101 | hygiene: &Hygiene, | 101 | hygiene: &Hygiene, |
102 | ) -> Self { | 102 | ) -> Self { |
103 | let entries = collect_attrs(owner) | 103 | let entries = collect_attrs(owner) |
104 | .enumerate() | 104 | .flat_map(|(id, attr)| match attr { |
105 | .flat_map(|(i, attr)| { | 105 | Either::Left(attr) => Attr::from_src(db, attr, hygiene, id), |
106 | let index = AttrId(i as u32); | 106 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { |
107 | match attr { | 107 | id, |
108 | Either::Left(attr) => Attr::from_src(db, attr, hygiene, index), | 108 | input: Some(AttrInput::Literal(SmolStr::new(doc))), |
109 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { | 109 | path: Interned::new(ModPath::from(hir_expand::name!(doc))), |
110 | id: index, | 110 | }), |
111 | input: Some(AttrInput::Literal(SmolStr::new(doc))), | ||
112 | path: Interned::new(ModPath::from(hir_expand::name!(doc))), | ||
113 | }), | ||
114 | } | ||
115 | }) | 111 | }) |
116 | .collect::<Arc<_>>(); | 112 | .collect::<Arc<_>>(); |
117 | 113 | ||
@@ -124,6 +120,7 @@ impl RawAttrs { | |||
124 | } | 120 | } |
125 | 121 | ||
126 | pub(crate) fn merge(&self, other: Self) -> Self { | 122 | pub(crate) fn merge(&self, other: Self) -> Self { |
123 | // FIXME: This needs to fixup `AttrId`s | ||
127 | match (&self.entries, &other.entries) { | 124 | match (&self.entries, &other.entries) { |
128 | (None, None) => Self::EMPTY, | 125 | (None, None) => Self::EMPTY, |
129 | (Some(entries), None) | (None, Some(entries)) => { | 126 | (Some(entries), None) | (None, Some(entries)) => { |
@@ -375,39 +372,26 @@ impl AttrsWithOwner { | |||
375 | 372 | ||
376 | let def_map = module.def_map(db); | 373 | let def_map = module.def_map(db); |
377 | let mod_data = &def_map[module.local_id]; | 374 | let mod_data = &def_map[module.local_id]; |
378 | let attrs = match mod_data.declaration_source(db) { | 375 | match mod_data.declaration_source(db) { |
379 | Some(it) => { | 376 | Some(it) => { |
380 | let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner) | 377 | let mut map = AttrSourceMap::new(InFile::new(it.file_id, &it.value)); |
381 | .map(|attr| InFile::new(it.file_id, attr)) | ||
382 | .collect(); | ||
383 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = | 378 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = |
384 | mod_data.definition_source(db) | 379 | mod_data.definition_source(db) |
385 | { | 380 | { |
386 | attrs.extend( | 381 | map.merge(AttrSourceMap::new(InFile::new(file_id, &file))); |
387 | collect_attrs(&file as &dyn ast::AttrsOwner) | ||
388 | .map(|attr| InFile::new(file_id, attr)), | ||
389 | ) | ||
390 | } | 382 | } |
391 | attrs | 383 | return map; |
392 | } | 384 | } |
393 | None => { | 385 | None => { |
394 | let InFile { file_id, value } = mod_data.definition_source(db); | 386 | let InFile { file_id, value } = mod_data.definition_source(db); |
395 | match &value { | 387 | let attrs_owner = match &value { |
396 | ModuleSource::SourceFile(file) => { | 388 | ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner, |
397 | collect_attrs(file as &dyn ast::AttrsOwner) | 389 | ModuleSource::Module(module) => module as &dyn ast::AttrsOwner, |
398 | } | 390 | ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner, |
399 | ModuleSource::Module(module) => { | 391 | }; |
400 | collect_attrs(module as &dyn ast::AttrsOwner) | 392 | return AttrSourceMap::new(InFile::new(file_id, attrs_owner)); |
401 | } | ||
402 | ModuleSource::BlockExpr(block) => { | ||
403 | collect_attrs(block as &dyn ast::AttrsOwner) | ||
404 | } | ||
405 | } | ||
406 | .map(|attr| InFile::new(file_id, attr)) | ||
407 | .collect() | ||
408 | } | 393 | } |
409 | }; | 394 | } |
410 | return AttrSourceMap { attrs }; | ||
411 | } | 395 | } |
412 | AttrDefId::FieldId(id) => { | 396 | AttrDefId::FieldId(id) => { |
413 | let map = db.fields_attrs_source_map(id.parent); | 397 | let map = db.fields_attrs_source_map(id.parent); |
@@ -462,11 +446,7 @@ impl AttrsWithOwner { | |||
462 | }, | 446 | }, |
463 | }; | 447 | }; |
464 | 448 | ||
465 | AttrSourceMap { | 449 | AttrSourceMap::new(owner.as_ref().map(|node| node as &dyn AttrsOwner)) |
466 | attrs: collect_attrs(&owner.value) | ||
467 | .map(|attr| InFile::new(owner.file_id, attr)) | ||
468 | .collect(), | ||
469 | } | ||
470 | } | 450 | } |
471 | 451 | ||
472 | pub fn docs_with_rangemap( | 452 | pub fn docs_with_rangemap( |
@@ -518,7 +498,7 @@ impl AttrsWithOwner { | |||
518 | if buf.is_empty() { | 498 | if buf.is_empty() { |
519 | None | 499 | None |
520 | } else { | 500 | } else { |
521 | Some((Documentation(buf), DocsRangeMap { mapping, source: self.source_map(db).attrs })) | 501 | Some((Documentation(buf), DocsRangeMap { mapping, source_map: self.source_map(db) })) |
522 | } | 502 | } |
523 | } | 503 | } |
524 | } | 504 | } |
@@ -559,27 +539,59 @@ fn inner_attributes( | |||
559 | } | 539 | } |
560 | 540 | ||
561 | pub struct AttrSourceMap { | 541 | pub struct AttrSourceMap { |
562 | attrs: Vec<InFile<Either<ast::Attr, ast::Comment>>>, | 542 | attrs: Vec<InFile<ast::Attr>>, |
543 | doc_comments: Vec<InFile<ast::Comment>>, | ||
563 | } | 544 | } |
564 | 545 | ||
565 | impl AttrSourceMap { | 546 | impl AttrSourceMap { |
547 | fn new(owner: InFile<&dyn ast::AttrsOwner>) -> Self { | ||
548 | let mut attrs = Vec::new(); | ||
549 | let mut doc_comments = Vec::new(); | ||
550 | for (_, attr) in collect_attrs(owner.value) { | ||
551 | match attr { | ||
552 | Either::Left(attr) => attrs.push(owner.with_value(attr)), | ||
553 | Either::Right(comment) => doc_comments.push(owner.with_value(comment)), | ||
554 | } | ||
555 | } | ||
556 | |||
557 | Self { attrs, doc_comments } | ||
558 | } | ||
559 | |||
560 | fn merge(&mut self, other: Self) { | ||
561 | self.attrs.extend(other.attrs); | ||
562 | self.doc_comments.extend(other.doc_comments); | ||
563 | } | ||
564 | |||
566 | /// Maps the lowered `Attr` back to its original syntax node. | 565 | /// Maps the lowered `Attr` back to its original syntax node. |
567 | /// | 566 | /// |
568 | /// `attr` must come from the `owner` used for AttrSourceMap | 567 | /// `attr` must come from the `owner` used for AttrSourceMap |
569 | /// | 568 | /// |
570 | /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of | 569 | /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of |
571 | /// the attribute represented by `Attr`. | 570 | /// the attribute represented by `Attr`. |
572 | pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> { | 571 | pub fn source_of(&self, attr: &Attr) -> InFile<Either<ast::Attr, ast::Comment>> { |
573 | self.attrs | 572 | self.source_of_id(attr.id) |
574 | .get(attr.id.0 as usize) | 573 | } |
575 | .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", attr.id)) | 574 | |
576 | .as_ref() | 575 | fn source_of_id(&self, id: AttrId) -> InFile<Either<ast::Attr, ast::Comment>> { |
576 | if id.is_doc_comment { | ||
577 | self.doc_comments | ||
578 | .get(id.ast_index as usize) | ||
579 | .unwrap_or_else(|| panic!("cannot find doc comment at index {:?}", id)) | ||
580 | .clone() | ||
581 | .map(|attr| Either::Right(attr)) | ||
582 | } else { | ||
583 | self.attrs | ||
584 | .get(id.ast_index as usize) | ||
585 | .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", id)) | ||
586 | .clone() | ||
587 | .map(|attr| Either::Left(attr)) | ||
588 | } | ||
577 | } | 589 | } |
578 | } | 590 | } |
579 | 591 | ||
580 | /// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree. | 592 | /// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree. |
581 | pub struct DocsRangeMap { | 593 | pub struct DocsRangeMap { |
582 | source: Vec<InFile<Either<ast::Attr, ast::Comment>>>, | 594 | source_map: AttrSourceMap, |
583 | // (docstring-line-range, attr_index, attr-string-range) | 595 | // (docstring-line-range, attr_index, attr-string-range) |
584 | // a mapping from the text range of a line of the [`Documentation`] to the attribute index and | 596 | // a mapping from the text range of a line of the [`Documentation`] to the attribute index and |
585 | // the original (untrimmed) syntax doc line | 597 | // the original (untrimmed) syntax doc line |
@@ -596,7 +608,7 @@ impl DocsRangeMap { | |||
596 | 608 | ||
597 | let relative_range = range - line_docs_range.start(); | 609 | let relative_range = range - line_docs_range.start(); |
598 | 610 | ||
599 | let &InFile { file_id, value: ref source } = &self.source[idx.0 as usize]; | 611 | let &InFile { file_id, value: ref source } = &self.source_map.source_of_id(idx); |
600 | match source { | 612 | match source { |
601 | Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here | 613 | Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here |
602 | // as well as for whats done in syntax highlight doc injection | 614 | // as well as for whats done in syntax highlight doc injection |
@@ -615,6 +627,12 @@ impl DocsRangeMap { | |||
615 | } | 627 | } |
616 | } | 628 | } |
617 | 629 | ||
630 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
631 | pub(crate) struct AttrId { | ||
632 | is_doc_comment: bool, | ||
633 | pub(crate) ast_index: u32, | ||
634 | } | ||
635 | |||
618 | #[derive(Debug, Clone, PartialEq, Eq)] | 636 | #[derive(Debug, Clone, PartialEq, Eq)] |
619 | pub struct Attr { | 637 | pub struct Attr { |
620 | pub(crate) id: AttrId, | 638 | pub(crate) id: AttrId, |
@@ -749,22 +767,32 @@ fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase | |||
749 | 767 | ||
750 | fn collect_attrs( | 768 | fn collect_attrs( |
751 | owner: &dyn ast::AttrsOwner, | 769 | owner: &dyn ast::AttrsOwner, |
752 | ) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> { | 770 | ) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> { |
753 | let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) | 771 | let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) |
754 | .map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs))); | 772 | .map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs))); |
755 | 773 | ||
756 | let outer_attrs = owner.attrs().filter(|attr| attr.kind().is_outer()); | 774 | let outer_attrs = owner.attrs().filter(|attr| attr.kind().is_outer()); |
757 | let attrs = outer_attrs | 775 | let attrs = |
758 | .chain(inner_attrs.into_iter().flatten()) | 776 | outer_attrs.chain(inner_attrs.into_iter().flatten()).enumerate().map(|(idx, attr)| { |
759 | .map(|attr| (attr.syntax().text_range().start(), Either::Left(attr))); | 777 | ( |
778 | AttrId { ast_index: idx as u32, is_doc_comment: false }, | ||
779 | attr.syntax().text_range().start(), | ||
780 | Either::Left(attr), | ||
781 | ) | ||
782 | }); | ||
760 | 783 | ||
761 | let outer_docs = | 784 | let outer_docs = |
762 | ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer); | 785 | ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer); |
763 | let docs = outer_docs | 786 | let docs = |
764 | .chain(inner_docs.into_iter().flatten()) | 787 | outer_docs.chain(inner_docs.into_iter().flatten()).enumerate().map(|(idx, docs_text)| { |
765 | .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text))); | 788 | ( |
789 | AttrId { ast_index: idx as u32, is_doc_comment: true }, | ||
790 | docs_text.syntax().text_range().start(), | ||
791 | Either::Right(docs_text), | ||
792 | ) | ||
793 | }); | ||
766 | // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved | 794 | // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved |
767 | docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).map(|(_, attr)| attr) | 795 | docs.chain(attrs).sorted_by_key(|&(_, offset, _)| offset).map(|(id, _, attr)| (id, attr)) |
768 | } | 796 | } |
769 | 797 | ||
770 | pub(crate) fn variants_attrs_source_map( | 798 | pub(crate) fn variants_attrs_source_map( |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 8360426f1..98b485b60 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -21,8 +21,6 @@ use profile::Count; | |||
21 | use rustc_hash::FxHashMap; | 21 | use rustc_hash::FxHashMap; |
22 | use syntax::{ast, AstNode, AstPtr}; | 22 | use syntax::{ast, AstNode, AstPtr}; |
23 | 23 | ||
24 | pub use lower::LowerCtx; | ||
25 | |||
26 | use crate::{ | 24 | use crate::{ |
27 | attr::{Attrs, RawAttrs}, | 25 | attr::{Attrs, RawAttrs}, |
28 | db::DefDatabase, | 26 | db::DefDatabase, |
@@ -35,6 +33,8 @@ use crate::{ | |||
35 | UnresolvedMacro, | 33 | UnresolvedMacro, |
36 | }; | 34 | }; |
37 | 35 | ||
36 | pub use lower::LowerCtx; | ||
37 | |||
38 | /// A subset of Expander that only deals with cfg attributes. We only need it to | 38 | /// A subset of Expander that only deals with cfg attributes. We only need it to |
39 | /// avoid cyclic queries in crate def map during enum processing. | 39 | /// avoid cyclic queries in crate def map during enum processing. |
40 | #[derive(Debug)] | 40 | #[derive(Debug)] |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 75dc19c11..2a7e0205f 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -205,7 +205,7 @@ impl ExprCollector<'_> { | |||
205 | self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr()) | 205 | self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr()) |
206 | } | 206 | } |
207 | 207 | ||
208 | /// Returns `None` if the expression is `#[cfg]`d out. | 208 | /// Returns `None` if and only if the expression is `#[cfg]`d out. |
209 | fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> { | 209 | fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> { |
210 | let syntax_ptr = AstPtr::new(&expr); | 210 | let syntax_ptr = AstPtr::new(&expr); |
211 | self.check_cfg(&expr)?; | 211 | self.check_cfg(&expr)?; |
@@ -668,7 +668,7 @@ impl ExprCollector<'_> { | |||
668 | if self.check_cfg(&stmt).is_none() { | 668 | if self.check_cfg(&stmt).is_none() { |
669 | return; | 669 | return; |
670 | } | 670 | } |
671 | 671 | let has_semi = stmt.semicolon_token().is_some(); | |
672 | // Note that macro could be expended to multiple statements | 672 | // Note that macro could be expended to multiple statements |
673 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { | 673 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { |
674 | let macro_ptr = AstPtr::new(&m); | 674 | let macro_ptr = AstPtr::new(&m); |
@@ -685,18 +685,19 @@ impl ExprCollector<'_> { | |||
685 | statements.statements().for_each(|stmt| this.collect_stmt(stmt)); | 685 | statements.statements().for_each(|stmt| this.collect_stmt(stmt)); |
686 | if let Some(expr) = statements.expr() { | 686 | if let Some(expr) = statements.expr() { |
687 | let expr = this.collect_expr(expr); | 687 | let expr = this.collect_expr(expr); |
688 | this.statements_in_scope.push(Statement::Expr(expr)); | 688 | this.statements_in_scope |
689 | .push(Statement::Expr { expr, has_semi }); | ||
689 | } | 690 | } |
690 | } | 691 | } |
691 | None => { | 692 | None => { |
692 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); | 693 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); |
693 | this.statements_in_scope.push(Statement::Expr(expr)); | 694 | this.statements_in_scope.push(Statement::Expr { expr, has_semi }); |
694 | } | 695 | } |
695 | }, | 696 | }, |
696 | ); | 697 | ); |
697 | } else { | 698 | } else { |
698 | let expr = self.collect_expr_opt(stmt.expr()); | 699 | let expr = self.collect_expr_opt(stmt.expr()); |
699 | self.statements_in_scope.push(Statement::Expr(expr)); | 700 | self.statements_in_scope.push(Statement::Expr { expr, has_semi }); |
700 | } | 701 | } |
701 | } | 702 | } |
702 | ast::Stmt::Item(item) => { | 703 | ast::Stmt::Item(item) => { |
@@ -725,8 +726,17 @@ impl ExprCollector<'_> { | |||
725 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | 726 | let prev_statements = std::mem::take(&mut self.statements_in_scope); |
726 | 727 | ||
727 | block.statements().for_each(|s| self.collect_stmt(s)); | 728 | block.statements().for_each(|s| self.collect_stmt(s)); |
728 | 729 | block.tail_expr().and_then(|e| { | |
729 | let tail = block.tail_expr().map(|e| self.collect_expr(e)); | 730 | let expr = self.maybe_collect_expr(e)?; |
731 | Some(self.statements_in_scope.push(Statement::Expr { expr, has_semi: false })) | ||
732 | }); | ||
733 | |||
734 | let mut tail = None; | ||
735 | if let Some(Statement::Expr { expr, has_semi: false }) = self.statements_in_scope.last() { | ||
736 | tail = Some(*expr); | ||
737 | self.statements_in_scope.pop(); | ||
738 | } | ||
739 | let tail = tail; | ||
730 | let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); | 740 | let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements); |
731 | let syntax_node_ptr = AstPtr::new(&block.into()); | 741 | let syntax_node_ptr = AstPtr::new(&block.into()); |
732 | let expr_id = self.alloc_expr( | 742 | let expr_id = self.alloc_expr( |
@@ -996,23 +1006,27 @@ impl From<ast::BinOp> for BinaryOp { | |||
996 | impl From<ast::LiteralKind> for Literal { | 1006 | impl From<ast::LiteralKind> for Literal { |
997 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { | 1007 | fn from(ast_lit_kind: ast::LiteralKind) -> Self { |
998 | match ast_lit_kind { | 1008 | match ast_lit_kind { |
1009 | // FIXME: these should have actual values filled in, but unsure on perf impact | ||
999 | LiteralKind::IntNumber(lit) => { | 1010 | LiteralKind::IntNumber(lit) => { |
1000 | if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { | 1011 | if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { |
1001 | return Literal::Float(Default::default(), builtin); | 1012 | return Literal::Float(Default::default(), builtin); |
1002 | } else if let builtin @ Some(_) = | 1013 | } else if let builtin @ Some(_) = |
1003 | lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)) | 1014 | lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)) |
1004 | { | 1015 | { |
1005 | Literal::Int(Default::default(), builtin) | 1016 | Literal::Int(lit.value().unwrap_or(0) as i128, builtin) |
1006 | } else { | 1017 | } else { |
1007 | let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it)); | 1018 | let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it)); |
1008 | Literal::Uint(Default::default(), builtin) | 1019 | Literal::Uint(lit.value().unwrap_or(0), builtin) |
1009 | } | 1020 | } |
1010 | } | 1021 | } |
1011 | LiteralKind::FloatNumber(lit) => { | 1022 | LiteralKind::FloatNumber(lit) => { |
1012 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); | 1023 | let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); |
1013 | Literal::Float(Default::default(), ty) | 1024 | Literal::Float(Default::default(), ty) |
1014 | } | 1025 | } |
1015 | LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), | 1026 | LiteralKind::ByteString(bs) => { |
1027 | let text = bs.value().map(Vec::from).unwrap_or_else(Default::default); | ||
1028 | Literal::ByteString(text) | ||
1029 | } | ||
1016 | LiteralKind::String(_) => Literal::String(Default::default()), | 1030 | LiteralKind::String(_) => Literal::String(Default::default()), |
1017 | LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), | 1031 | LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), |
1018 | LiteralKind::Bool(val) => Literal::Bool(val), | 1032 | LiteralKind::Bool(val) => Literal::Bool(val), |
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index bd7005ca6..6764de3a7 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -157,7 +157,7 @@ fn compute_block_scopes( | |||
157 | scope = scopes.new_scope(scope); | 157 | scope = scopes.new_scope(scope); |
158 | scopes.add_bindings(body, scope, *pat); | 158 | scopes.add_bindings(body, scope, *pat); |
159 | } | 159 | } |
160 | Statement::Expr(expr) => { | 160 | Statement::Expr { expr, .. } => { |
161 | scopes.set_scope(*expr, scope); | 161 | scopes.set_scope(*expr, scope); |
162 | compute_expr_scopes(*expr, body, scopes, scope); | 162 | compute_expr_scopes(*expr, body, scopes, scope); |
163 | } | 163 | } |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index b4ad984bd..2ba619d23 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -43,8 +43,8 @@ pub enum Literal { | |||
43 | ByteString(Vec<u8>), | 43 | ByteString(Vec<u8>), |
44 | Char(char), | 44 | Char(char), |
45 | Bool(bool), | 45 | Bool(bool), |
46 | Int(u64, Option<BuiltinInt>), | 46 | Int(i128, Option<BuiltinInt>), |
47 | Uint(u64, Option<BuiltinUint>), | 47 | Uint(u128, Option<BuiltinUint>), |
48 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq | 48 | Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq |
49 | } | 49 | } |
50 | 50 | ||
@@ -242,7 +242,7 @@ pub struct RecordLitField { | |||
242 | #[derive(Debug, Clone, Eq, PartialEq)] | 242 | #[derive(Debug, Clone, Eq, PartialEq)] |
243 | pub enum Statement { | 243 | pub enum Statement { |
244 | Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> }, | 244 | Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> }, |
245 | Expr(ExprId), | 245 | Expr { expr: ExprId, has_semi: bool }, |
246 | } | 246 | } |
247 | 247 | ||
248 | impl Expr { | 248 | impl Expr { |
@@ -265,7 +265,7 @@ impl Expr { | |||
265 | f(*expr); | 265 | f(*expr); |
266 | } | 266 | } |
267 | } | 267 | } |
268 | Statement::Expr(e) => f(*e), | 268 | Statement::Expr { expr: expression, .. } => f(*expression), |
269 | } | 269 | } |
270 | } | 270 | } |
271 | if let Some(expr) = tail { | 271 | if let Some(expr) = tail { |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 858e88038..ee52794aa 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -5,10 +5,10 @@ use std::iter; | |||
5 | use hir_expand::name::{known, AsName, Name}; | 5 | use hir_expand::name::{known, AsName, Name}; |
6 | use rustc_hash::FxHashSet; | 6 | use rustc_hash::FxHashSet; |
7 | 7 | ||
8 | use crate::nameres::DefMap; | ||
9 | use crate::{ | 8 | use crate::{ |
10 | db::DefDatabase, | 9 | db::DefDatabase, |
11 | item_scope::ItemInNs, | 10 | item_scope::ItemInNs, |
11 | nameres::DefMap, | ||
12 | path::{ModPath, PathKind}, | 12 | path::{ModPath, PathKind}, |
13 | visibility::Visibility, | 13 | visibility::Visibility, |
14 | ModuleDefId, ModuleId, | 14 | ModuleDefId, ModuleId, |
@@ -134,7 +134,16 @@ fn find_path_inner( | |||
134 | for (name, def_id) in root_def_map.extern_prelude() { | 134 | for (name, def_id) in root_def_map.extern_prelude() { |
135 | if item == ItemInNs::Types(*def_id) { | 135 | if item == ItemInNs::Types(*def_id) { |
136 | let name = scope_name.unwrap_or_else(|| name.clone()); | 136 | let name = scope_name.unwrap_or_else(|| name.clone()); |
137 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); | 137 | |
138 | let name_already_occupied_in_type_ns = def_map | ||
139 | .with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { | ||
140 | def_map[local_id].scope.get(&name).take_types().filter(|&id| id != *def_id) | ||
141 | }) | ||
142 | .is_some(); | ||
143 | return Some(ModPath::from_segments( | ||
144 | if name_already_occupied_in_type_ns { PathKind::Abs } else { PathKind::Plain }, | ||
145 | vec![name], | ||
146 | )); | ||
138 | } | 147 | } |
139 | } | 148 | } |
140 | 149 | ||
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 8d13c7e04..cad8a7479 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -18,7 +18,7 @@ use hir_expand::{ | |||
18 | ast_id_map::FileAstId, | 18 | ast_id_map::FileAstId, |
19 | hygiene::Hygiene, | 19 | hygiene::Hygiene, |
20 | name::{name, AsName, Name}, | 20 | name::{name, AsName, Name}, |
21 | HirFileId, InFile, | 21 | FragmentKind, HirFileId, InFile, |
22 | }; | 22 | }; |
23 | use la_arena::{Arena, Idx, RawIdx}; | 23 | use la_arena::{Arena, Idx, RawIdx}; |
24 | use profile::Count; | 24 | use profile::Count; |
@@ -656,6 +656,7 @@ pub struct MacroCall { | |||
656 | /// Path to the called macro. | 656 | /// Path to the called macro. |
657 | pub path: Interned<ModPath>, | 657 | pub path: Interned<ModPath>, |
658 | pub ast_id: FileAstId<ast::MacroCall>, | 658 | pub ast_id: FileAstId<ast::MacroCall>, |
659 | pub fragment: FragmentKind, | ||
659 | } | 660 | } |
660 | 661 | ||
661 | #[derive(Debug, Clone, Eq, PartialEq)] | 662 | #[derive(Debug, Clone, Eq, PartialEq)] |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5743b3386..fe348091d 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -624,7 +624,8 @@ impl<'a> Ctx<'a> { | |||
624 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { | 624 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { |
625 | let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?); | 625 | let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?); |
626 | let ast_id = self.source_ast_id_map.ast_id(m); | 626 | let ast_id = self.source_ast_id_map.ast_id(m); |
627 | let res = MacroCall { path, ast_id }; | 627 | let fragment = hir_expand::to_fragment_kind(m); |
628 | let res = MacroCall { path, ast_id, fragment }; | ||
628 | Some(id(self.data().macro_calls.alloc(res))) | 629 | Some(id(self.data().macro_calls.alloc(res))) |
629 | } | 630 | } |
630 | 631 | ||
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index da46f16f7..a82ea5957 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -62,13 +62,14 @@ use hir_expand::{ | |||
62 | ast_id_map::FileAstId, | 62 | ast_id_map::FileAstId, |
63 | eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, | 63 | eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, |
64 | hygiene::Hygiene, | 64 | hygiene::Hygiene, |
65 | AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 65 | AstId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
66 | }; | 66 | }; |
67 | use la_arena::Idx; | 67 | use la_arena::Idx; |
68 | use nameres::DefMap; | 68 | use nameres::DefMap; |
69 | use path::ModPath; | 69 | use path::ModPath; |
70 | use syntax::ast; | 70 | use syntax::ast; |
71 | 71 | ||
72 | use crate::attr::AttrId; | ||
72 | use crate::builtin_type::BuiltinType; | 73 | use crate::builtin_type::BuiltinType; |
73 | use item_tree::{ | 74 | use item_tree::{ |
74 | Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait, | 75 | Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait, |
@@ -652,6 +653,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
652 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 653 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
653 | mut error_sink: &mut dyn FnMut(mbe::ExpandError), | 654 | mut error_sink: &mut dyn FnMut(mbe::ExpandError), |
654 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { | 655 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { |
656 | let fragment = hir_expand::to_fragment_kind(self.value); | ||
655 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); | 657 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); |
656 | let h = Hygiene::new(db.upcast(), self.file_id); | 658 | let h = Hygiene::new(db.upcast(), self.file_id); |
657 | let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h)); | 659 | let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h)); |
@@ -667,6 +669,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
667 | 669 | ||
668 | macro_call_as_call_id( | 670 | macro_call_as_call_id( |
669 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), | 671 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), |
672 | fragment, | ||
670 | db, | 673 | db, |
671 | krate, | 674 | krate, |
672 | resolver, | 675 | resolver, |
@@ -695,6 +698,7 @@ pub struct UnresolvedMacro { | |||
695 | 698 | ||
696 | fn macro_call_as_call_id( | 699 | fn macro_call_as_call_id( |
697 | call: &AstIdWithPath<ast::MacroCall>, | 700 | call: &AstIdWithPath<ast::MacroCall>, |
701 | fragment: FragmentKind, | ||
698 | db: &dyn db::DefDatabase, | 702 | db: &dyn db::DefDatabase, |
699 | krate: CrateId, | 703 | krate: CrateId, |
700 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 704 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
@@ -718,7 +722,11 @@ fn macro_call_as_call_id( | |||
718 | .map(MacroCallId::from) | 722 | .map(MacroCallId::from) |
719 | } else { | 723 | } else { |
720 | Ok(def | 724 | Ok(def |
721 | .as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id }) | 725 | .as_lazy_macro( |
726 | db.upcast(), | ||
727 | krate, | ||
728 | MacroCallKind::FnLike { ast_id: call.ast_id, fragment }, | ||
729 | ) | ||
722 | .into()) | 730 | .into()) |
723 | }; | 731 | }; |
724 | Ok(res) | 732 | Ok(res) |
@@ -745,7 +753,7 @@ fn derive_macro_as_call_id( | |||
745 | MacroCallKind::Derive { | 753 | MacroCallKind::Derive { |
746 | ast_id: item_attr.ast_id, | 754 | ast_id: item_attr.ast_id, |
747 | derive_name: last_segment.to_string(), | 755 | derive_name: last_segment.to_string(), |
748 | derive_attr, | 756 | derive_attr_index: derive_attr.ast_index, |
749 | }, | 757 | }, |
750 | ) | 758 | ) |
751 | .into(); | 759 | .into(); |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 1bc72ec1f..249af6fc8 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -629,7 +629,7 @@ mod diagnostics { | |||
629 | DiagnosticKind::UnresolvedProcMacro { ast } => { | 629 | DiagnosticKind::UnresolvedProcMacro { ast } => { |
630 | let mut precise_location = None; | 630 | let mut precise_location = None; |
631 | let (file, ast, name) = match ast { | 631 | let (file, ast, name) = match ast { |
632 | MacroCallKind::FnLike { ast_id } => { | 632 | MacroCallKind::FnLike { ast_id, .. } => { |
633 | let node = ast_id.to_node(db.upcast()); | 633 | let node = ast_id.to_node(db.upcast()); |
634 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) | 634 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) |
635 | } | 635 | } |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 05ceb1efb..19db6cc59 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,14 +13,14 @@ 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 | AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 16 | FragmentKind, 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}; |
20 | use syntax::ast; | 20 | use syntax::ast; |
21 | 21 | ||
22 | use crate::{ | 22 | use crate::{ |
23 | attr::Attrs, | 23 | attr::{AttrId, Attrs}, |
24 | db::DefDatabase, | 24 | db::DefDatabase, |
25 | derive_macro_as_call_id, | 25 | derive_macro_as_call_id, |
26 | intern::Interned, | 26 | intern::Interned, |
@@ -215,7 +215,7 @@ struct MacroDirective { | |||
215 | 215 | ||
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>, fragment: FragmentKind }, |
219 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, | 219 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, |
220 | } | 220 | } |
221 | 221 | ||
@@ -481,6 +481,11 @@ impl DefCollector<'_> { | |||
481 | let res = self.def_map.resolve_name_in_extern_prelude(self.db, &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 | if m == self.def_map.module_id(current_module_id) { | ||
485 | cov_mark::hit!(ignore_macro_use_extern_crate_self); | ||
486 | return; | ||
487 | } | ||
488 | |||
484 | cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); | 489 | cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); |
485 | self.import_all_macros_exported(current_module_id, m.krate); | 490 | self.import_all_macros_exported(current_module_id, m.krate); |
486 | } | 491 | } |
@@ -807,9 +812,10 @@ impl DefCollector<'_> { | |||
807 | let mut res = ReachedFixedPoint::Yes; | 812 | let mut res = ReachedFixedPoint::Yes; |
808 | macros.retain(|directive| { | 813 | macros.retain(|directive| { |
809 | match &directive.kind { | 814 | match &directive.kind { |
810 | MacroDirectiveKind::FnLike { ast_id } => { | 815 | MacroDirectiveKind::FnLike { ast_id, fragment } => { |
811 | match macro_call_as_call_id( | 816 | match macro_call_as_call_id( |
812 | ast_id, | 817 | ast_id, |
818 | *fragment, | ||
813 | self.db, | 819 | self.db, |
814 | self.def_map.krate, | 820 | self.def_map.krate, |
815 | |path| { | 821 | |path| { |
@@ -926,8 +932,9 @@ impl DefCollector<'_> { | |||
926 | 932 | ||
927 | for directive in &self.unexpanded_macros { | 933 | for directive in &self.unexpanded_macros { |
928 | match &directive.kind { | 934 | match &directive.kind { |
929 | MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id( | 935 | MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id( |
930 | ast_id, | 936 | ast_id, |
937 | *fragment, | ||
931 | self.db, | 938 | self.db, |
932 | self.def_map.krate, | 939 | self.def_map.krate, |
933 | |path| { | 940 | |path| { |
@@ -1496,6 +1503,7 @@ impl ModCollector<'_, '_> { | |||
1496 | let mut error = None; | 1503 | let mut error = None; |
1497 | match macro_call_as_call_id( | 1504 | match macro_call_as_call_id( |
1498 | &ast_id, | 1505 | &ast_id, |
1506 | mac.fragment, | ||
1499 | self.def_collector.db, | 1507 | self.def_collector.db, |
1500 | self.def_collector.def_map.krate, | 1508 | self.def_collector.def_map.krate, |
1501 | |path| { | 1509 | |path| { |
@@ -1524,9 +1532,14 @@ impl ModCollector<'_, '_> { | |||
1524 | } | 1532 | } |
1525 | Ok(Err(_)) => { | 1533 | Ok(Err(_)) => { |
1526 | // Built-in macro failed eager expansion. | 1534 | // Built-in macro failed eager expansion. |
1535 | |||
1536 | // FIXME: don't parse the file here | ||
1537 | let fragment = hir_expand::to_fragment_kind( | ||
1538 | &ast_id.ast_id.to_node(self.def_collector.db.upcast()), | ||
1539 | ); | ||
1527 | self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( | 1540 | self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( |
1528 | self.module_id, | 1541 | self.module_id, |
1529 | MacroCallKind::FnLike { ast_id: ast_id.ast_id }, | 1542 | MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment }, |
1530 | error.unwrap().to_string(), | 1543 | error.unwrap().to_string(), |
1531 | )); | 1544 | )); |
1532 | return; | 1545 | return; |
@@ -1543,7 +1556,7 @@ impl ModCollector<'_, '_> { | |||
1543 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1556 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1544 | module_id: self.module_id, | 1557 | module_id: self.module_id, |
1545 | depth: self.macro_depth + 1, | 1558 | depth: self.macro_depth + 1, |
1546 | kind: MacroDirectiveKind::FnLike { ast_id }, | 1559 | kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment }, |
1547 | }); | 1560 | }); |
1548 | } | 1561 | } |
1549 | 1562 | ||
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index 4f2e7a2f9..9f652731d 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -411,6 +411,22 @@ struct Arc; | |||
411 | } | 411 | } |
412 | 412 | ||
413 | #[test] | 413 | #[test] |
414 | fn macro_use_extern_crate_self() { | ||
415 | cov_mark::check!(ignore_macro_use_extern_crate_self); | ||
416 | check( | ||
417 | r#" | ||
418 | //- /main.rs crate:main | ||
419 | #[macro_use] | ||
420 | extern crate self as bla; | ||
421 | "#, | ||
422 | expect![[r#" | ||
423 | crate | ||
424 | bla: t | ||
425 | "#]], | ||
426 | ); | ||
427 | } | ||
428 | |||
429 | #[test] | ||
414 | fn reexport_across_crates() { | 430 | fn reexport_across_crates() { |
415 | check( | 431 | check( |
416 | r#" | 432 | r#" |
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs index 227ecd162..d884a6eb4 100644 --- a/crates/hir_def/src/nameres/tests/incremental.rs +++ b/crates/hir_def/src/nameres/tests/incremental.rs | |||
@@ -137,6 +137,9 @@ m!(Z); | |||
137 | }); | 137 | }); |
138 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); | 138 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); |
139 | assert_eq!(n_recalculated_item_trees, 6); | 139 | assert_eq!(n_recalculated_item_trees, 6); |
140 | let n_reparsed_macros = | ||
141 | events.iter().filter(|it| it.contains("parse_macro_expansion")).count(); | ||
142 | assert_eq!(n_reparsed_macros, 3); | ||
140 | } | 143 | } |
141 | 144 | ||
142 | let new_text = r#" | 145 | let new_text = r#" |
@@ -155,5 +158,8 @@ m!(Z); | |||
155 | }); | 158 | }); |
156 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); | 159 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); |
157 | assert_eq!(n_recalculated_item_trees, 1); | 160 | assert_eq!(n_recalculated_item_trees, 1); |
161 | let n_reparsed_macros = | ||
162 | events.iter().filter(|it| it.contains("parse_macro_expansion")).count(); | ||
163 | assert_eq!(n_reparsed_macros, 0); | ||
158 | } | 164 | } |
159 | } | 165 | } |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index ea29da5da..9e44547cb 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | //! be directly created from an ast::TypeRef, without further queries. | 2 | //! be directly created from an ast::TypeRef, without further queries. |
3 | 3 | ||
4 | use hir_expand::{name::Name, AstId, InFile}; | 4 | use hir_expand::{name::Name, AstId, InFile}; |
5 | use std::convert::TryInto; | ||
5 | use syntax::ast; | 6 | use syntax::ast; |
6 | 7 | ||
7 | use crate::{body::LowerCtx, path::Path}; | 8 | use crate::{body::LowerCtx, path::Path}; |
@@ -79,7 +80,9 @@ pub enum TypeRef { | |||
79 | Path(Path), | 80 | Path(Path), |
80 | RawPtr(Box<TypeRef>, Mutability), | 81 | RawPtr(Box<TypeRef>, Mutability), |
81 | Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability), | 82 | Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability), |
82 | Array(Box<TypeRef> /*, Expr*/), | 83 | // FIXME: for full const generics, the latter element (length) here is going to have to be an |
84 | // expression that is further lowered later in hir_ty. | ||
85 | Array(Box<TypeRef>, ConstScalar), | ||
83 | Slice(Box<TypeRef>), | 86 | Slice(Box<TypeRef>), |
84 | /// A fn pointer. Last element of the vector is the return type. | 87 | /// A fn pointer. Last element of the vector is the return type. |
85 | Fn(Vec<TypeRef>, bool /*varargs*/), | 88 | Fn(Vec<TypeRef>, bool /*varargs*/), |
@@ -140,7 +143,16 @@ impl TypeRef { | |||
140 | TypeRef::RawPtr(Box::new(inner_ty), mutability) | 143 | TypeRef::RawPtr(Box::new(inner_ty), mutability) |
141 | } | 144 | } |
142 | ast::Type::ArrayType(inner) => { | 145 | ast::Type::ArrayType(inner) => { |
143 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) | 146 | // FIXME: This is a hack. We should probably reuse the machinery of |
147 | // `hir_def::body::lower` to lower this into an `Expr` and then evaluate it at the | ||
148 | // `hir_ty` level, which would allow knowing the type of: | ||
149 | // let v: [u8; 2 + 2] = [0u8; 4]; | ||
150 | let len = inner | ||
151 | .expr() | ||
152 | .map(ConstScalar::usize_from_literal_expr) | ||
153 | .unwrap_or(ConstScalar::Unknown); | ||
154 | |||
155 | TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())), len) | ||
144 | } | 156 | } |
145 | ast::Type::SliceType(inner) => { | 157 | ast::Type::SliceType(inner) => { |
146 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) | 158 | TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty()))) |
@@ -212,7 +224,7 @@ impl TypeRef { | |||
212 | } | 224 | } |
213 | TypeRef::RawPtr(type_ref, _) | 225 | TypeRef::RawPtr(type_ref, _) |
214 | | TypeRef::Reference(type_ref, ..) | 226 | | TypeRef::Reference(type_ref, ..) |
215 | | TypeRef::Array(type_ref) | 227 | | TypeRef::Array(type_ref, _) |
216 | | TypeRef::Slice(type_ref) => go(&type_ref, f), | 228 | | TypeRef::Slice(type_ref) => go(&type_ref, f), |
217 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { | 229 | TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { |
218 | for bound in bounds { | 230 | for bound in bounds { |
@@ -298,3 +310,58 @@ impl TypeBound { | |||
298 | } | 310 | } |
299 | } | 311 | } |
300 | } | 312 | } |
313 | |||
314 | /// A concrete constant value | ||
315 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
316 | pub enum ConstScalar { | ||
317 | // for now, we only support the trivial case of constant evaluating the length of an array | ||
318 | // Note that this is u64 because the target usize may be bigger than our usize | ||
319 | Usize(u64), | ||
320 | |||
321 | /// Case of an unknown value that rustc might know but we don't | ||
322 | // FIXME: this is a hack to get around chalk not being able to represent unevaluatable | ||
323 | // constants | ||
324 | // https://github.com/rust-analyzer/rust-analyzer/pull/8813#issuecomment-840679177 | ||
325 | // https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/Handling.20non.20evaluatable.20constants'.20equality/near/238386348 | ||
326 | Unknown, | ||
327 | } | ||
328 | |||
329 | impl std::fmt::Display for ConstScalar { | ||
330 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { | ||
331 | match self { | ||
332 | ConstScalar::Usize(us) => write!(fmt, "{}", us), | ||
333 | ConstScalar::Unknown => write!(fmt, "_"), | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | |||
338 | impl ConstScalar { | ||
339 | /// Gets a target usize out of the ConstScalar | ||
340 | pub fn as_usize(&self) -> Option<u64> { | ||
341 | match self { | ||
342 | &ConstScalar::Usize(us) => Some(us), | ||
343 | _ => None, | ||
344 | } | ||
345 | } | ||
346 | |||
347 | // FIXME: as per the comments on `TypeRef::Array`, this evaluation should not happen at this | ||
348 | // parse stage. | ||
349 | fn usize_from_literal_expr(expr: ast::Expr) -> ConstScalar { | ||
350 | match expr { | ||
351 | ast::Expr::Literal(lit) => { | ||
352 | let lkind = lit.kind(); | ||
353 | match lkind { | ||
354 | ast::LiteralKind::IntNumber(num) | ||
355 | if num.suffix() == None || num.suffix() == Some("usize") => | ||
356 | { | ||
357 | num.value().and_then(|v| v.try_into().ok()) | ||
358 | } | ||
359 | _ => None, | ||
360 | } | ||
361 | } | ||
362 | _ => None, | ||
363 | } | ||
364 | .map(ConstScalar::Usize) | ||
365 | .unwrap_or(ConstScalar::Unknown) | ||
366 | } | ||
367 | } | ||