diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/adt.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model/src.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/expr/lower.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/generics.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/marks.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/name.rs | 157 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs | 41 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs | 105 | ||||
-rw-r--r-- | crates/ra_hir/src/path.rs | 64 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/type_ref.rs | 2 |
17 files changed, 361 insertions, 124 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index fbb4ff4d8..99d286215 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -133,7 +133,7 @@ impl VariantData { | |||
133 | .fields() | 133 | .fields() |
134 | .enumerate() | 134 | .enumerate() |
135 | .map(|(i, fd)| StructFieldData { | 135 | .map(|(i, fd)| StructFieldData { |
136 | name: Name::tuple_field_name(i), | 136 | name: Name::new_tuple_field(i), |
137 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), | 137 | type_ref: TypeRef::from_ast_opt(fd.type_ref()), |
138 | }) | 138 | }) |
139 | .collect(); | 139 | .collect(); |
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index c0cb27b47..dc964e156 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs | |||
@@ -119,7 +119,7 @@ impl HasSource for TypeAlias { | |||
119 | impl HasSource for MacroDef { | 119 | impl HasSource for MacroDef { |
120 | type Ast = ast::MacroCall; | 120 | type Ast = ast::MacroCall; |
121 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> { | 121 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> { |
122 | Source { file_id: self.id.0.file_id(), ast: self.id.0.to_node(db) } | 122 | Source { file_id: self.id.ast_id.file_id(), ast: self.id.ast_id.to_node(db) } |
123 | } | 123 | } |
124 | } | 124 | } |
125 | 125 | ||
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs index 61535d24f..6d6f60506 100644 --- a/crates/ra_hir/src/expr/lower.rs +++ b/crates/ra_hir/src/expr/lower.rs | |||
@@ -272,8 +272,11 @@ where | |||
272 | self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr) | 272 | self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr) |
273 | } | 273 | } |
274 | ast::Expr::PathExpr(e) => { | 274 | ast::Expr::PathExpr(e) => { |
275 | let path = | 275 | let path = e |
276 | e.path().and_then(Path::from_ast).map(Expr::Path).unwrap_or(Expr::Missing); | 276 | .path() |
277 | .and_then(|path| self.parse_path(path)) | ||
278 | .map(Expr::Path) | ||
279 | .unwrap_or(Expr::Missing); | ||
277 | self.alloc_expr(path, syntax_ptr) | 280 | self.alloc_expr(path, syntax_ptr) |
278 | } | 281 | } |
279 | ast::Expr::ContinueExpr(_e) => { | 282 | ast::Expr::ContinueExpr(_e) => { |
@@ -295,7 +298,7 @@ where | |||
295 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) | 298 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) |
296 | } | 299 | } |
297 | ast::Expr::RecordLit(e) => { | 300 | ast::Expr::RecordLit(e) => { |
298 | let path = e.path().and_then(Path::from_ast); | 301 | let path = e.path().and_then(|path| self.parse_path(path)); |
299 | let mut field_ptrs = Vec::new(); | 302 | let mut field_ptrs = Vec::new(); |
300 | let record_lit = if let Some(nfl) = e.record_field_list() { | 303 | let record_lit = if let Some(nfl) = e.record_field_list() { |
301 | let fields = nfl | 304 | let fields = nfl |
@@ -459,7 +462,7 @@ where | |||
459 | .ast_id(&e) | 462 | .ast_id(&e) |
460 | .with_file_id(self.current_file_id); | 463 | .with_file_id(self.current_file_id); |
461 | 464 | ||
462 | if let Some(path) = e.path().and_then(Path::from_ast) { | 465 | if let Some(path) = e.path().and_then(|path| self.parse_path(path)) { |
463 | if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) { | 466 | if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) { |
464 | let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db); | 467 | let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db); |
465 | let file_id = call_id.as_file(MacroFileKind::Expr); | 468 | let file_id = call_id.as_file(MacroFileKind::Expr); |
@@ -529,7 +532,7 @@ where | |||
529 | Pat::Bind { name, mode: annotation, subpat } | 532 | Pat::Bind { name, mode: annotation, subpat } |
530 | } | 533 | } |
531 | ast::Pat::TupleStructPat(p) => { | 534 | ast::Pat::TupleStructPat(p) => { |
532 | let path = p.path().and_then(Path::from_ast); | 535 | let path = p.path().and_then(|path| self.parse_path(path)); |
533 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 536 | let args = p.args().map(|p| self.collect_pat(p)).collect(); |
534 | Pat::TupleStruct { path, args } | 537 | Pat::TupleStruct { path, args } |
535 | } | 538 | } |
@@ -539,7 +542,7 @@ where | |||
539 | Pat::Ref { pat, mutability } | 542 | Pat::Ref { pat, mutability } |
540 | } | 543 | } |
541 | ast::Pat::PathPat(p) => { | 544 | ast::Pat::PathPat(p) => { |
542 | let path = p.path().and_then(Path::from_ast); | 545 | let path = p.path().and_then(|path| self.parse_path(path)); |
543 | path.map(Pat::Path).unwrap_or(Pat::Missing) | 546 | path.map(Pat::Path).unwrap_or(Pat::Missing) |
544 | } | 547 | } |
545 | ast::Pat::TuplePat(p) => { | 548 | ast::Pat::TuplePat(p) => { |
@@ -548,7 +551,7 @@ where | |||
548 | } | 551 | } |
549 | ast::Pat::PlaceholderPat(_) => Pat::Wild, | 552 | ast::Pat::PlaceholderPat(_) => Pat::Wild, |
550 | ast::Pat::RecordPat(p) => { | 553 | ast::Pat::RecordPat(p) => { |
551 | let path = p.path().and_then(Path::from_ast); | 554 | let path = p.path().and_then(|path| self.parse_path(path)); |
552 | let record_field_pat_list = | 555 | let record_field_pat_list = |
553 | p.record_field_pat_list().expect("every struct should have a field list"); | 556 | p.record_field_pat_list().expect("every struct should have a field list"); |
554 | let mut fields: Vec<_> = record_field_pat_list | 557 | let mut fields: Vec<_> = record_field_pat_list |
@@ -589,6 +592,10 @@ where | |||
589 | self.missing_pat() | 592 | self.missing_pat() |
590 | } | 593 | } |
591 | } | 594 | } |
595 | |||
596 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { | ||
597 | Path::from_src(Source { ast: path, file_id: self.current_file_id }, self.db) | ||
598 | } | ||
592 | } | 599 | } |
593 | 600 | ||
594 | impl From<ast::BinOp> for BinaryOp { | 601 | impl From<ast::BinOp> for BinaryOp { |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 6865d34ba..4ce7551c3 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -132,6 +132,7 @@ impl GenericParams { | |||
132 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { | 132 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { |
133 | for (idx, type_param) in params.type_params().enumerate() { | 133 | for (idx, type_param) in params.type_params().enumerate() { |
134 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 134 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
135 | // FIXME: Use `Path::from_src` | ||
135 | let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast); | 136 | let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast); |
136 | 137 | ||
137 | let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; | 138 | let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 9ea4e695d..bcbcd3dd7 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ast, AstNode, Parse, SyntaxNode}; | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::{AstDatabase, DefDatabase, InternDatabase}, | 12 | db::{AstDatabase, DefDatabase, InternDatabase}, |
13 | AstId, FileAstId, Module, Source, | 13 | AstId, Crate, FileAstId, Module, Source, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | /// hir makes heavy use of ids: integer (u32) handlers to various things. You | 16 | /// hir makes heavy use of ids: integer (u32) handlers to various things. You |
@@ -58,6 +58,17 @@ impl HirFileId { | |||
58 | } | 58 | } |
59 | } | 59 | } |
60 | 60 | ||
61 | /// Get the crate which the macro lives in, if it is a macro file. | ||
62 | pub(crate) fn macro_crate(self, db: &impl AstDatabase) -> Option<Crate> { | ||
63 | match self.0 { | ||
64 | HirFileIdRepr::File(_) => None, | ||
65 | HirFileIdRepr::Macro(macro_file) => { | ||
66 | let loc = macro_file.macro_call_id.loc(db); | ||
67 | Some(loc.def.krate) | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
61 | pub(crate) fn parse_or_expand_query( | 72 | pub(crate) fn parse_or_expand_query( |
62 | db: &impl AstDatabase, | 73 | db: &impl AstDatabase, |
63 | file_id: HirFileId, | 74 | file_id: HirFileId, |
@@ -121,10 +132,13 @@ impl From<FileId> for HirFileId { | |||
121 | } | 132 | } |
122 | 133 | ||
123 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 134 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
124 | pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>); | 135 | pub struct MacroDefId { |
136 | pub(crate) ast_id: AstId<ast::MacroCall>, | ||
137 | pub(crate) krate: Crate, | ||
138 | } | ||
125 | 139 | ||
126 | pub(crate) fn macro_def_query(db: &impl AstDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> { | 140 | pub(crate) fn macro_def_query(db: &impl AstDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> { |
127 | let macro_call = id.0.to_node(db); | 141 | let macro_call = id.ast_id.to_node(db); |
128 | let arg = macro_call.token_tree()?; | 142 | let arg = macro_call.token_tree()?; |
129 | let (tt, _) = mbe::ast_to_token_tree(&arg).or_else(|| { | 143 | let (tt, _) = mbe::ast_to_token_tree(&arg).or_else(|| { |
130 | log::warn!("fail on macro_def to token tree: {:#?}", arg); | 144 | log::warn!("fail on macro_def to token tree: {:#?}", arg); |
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index d830202bd..c66a1c6a6 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -218,7 +218,10 @@ impl ModuleImplBlocks { | |||
218 | ast::ItemOrMacro::Macro(macro_call) => { | 218 | ast::ItemOrMacro::Macro(macro_call) => { |
219 | //FIXME: we should really cut down on the boilerplate required to process a macro | 219 | //FIXME: we should really cut down on the boilerplate required to process a macro |
220 | let ast_id = db.ast_id_map(file_id).ast_id(¯o_call).with_file_id(file_id); | 220 | let ast_id = db.ast_id_map(file_id).ast_id(¯o_call).with_file_id(file_id); |
221 | if let Some(path) = macro_call.path().and_then(Path::from_ast) { | 221 | if let Some(path) = macro_call |
222 | .path() | ||
223 | .and_then(|path| Path::from_src(Source { ast: path, file_id }, db)) | ||
224 | { | ||
222 | if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path) | 225 | if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path) |
223 | { | 226 | { |
224 | let call_id = MacroCallLoc { def: def.id, ast_id }.id(db); | 227 | let call_id = MacroCallLoc { def: def.id, ast_id }.id(db); |
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index 125e0beea..0fed46802 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs | |||
@@ -13,4 +13,6 @@ test_utils::marks!( | |||
13 | macro_rules_from_other_crates_are_visible_with_macro_use | 13 | macro_rules_from_other_crates_are_visible_with_macro_use |
14 | prelude_is_macro_use | 14 | prelude_is_macro_use |
15 | coerce_merge_fail_fallback | 15 | coerce_merge_fail_fallback |
16 | macro_dollar_crate_self | ||
17 | macro_dollar_crate_other | ||
16 | ); | 18 | ); |
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index 1bf993ffb..d50867f5d 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs | |||
@@ -5,20 +5,21 @@ use ra_syntax::{ast, SmolStr}; | |||
5 | /// `Name` is a wrapper around string, which is used in hir for both references | 5 | /// `Name` is a wrapper around string, which is used in hir for both references |
6 | /// and declarations. In theory, names should also carry hygiene info, but we are | 6 | /// and declarations. In theory, names should also carry hygiene info, but we are |
7 | /// not there yet! | 7 | /// not there yet! |
8 | #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] | 8 | #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
9 | pub struct Name { | 9 | pub struct Name(Repr); |
10 | text: SmolStr, | ||
11 | } | ||
12 | 10 | ||
13 | impl fmt::Display for Name { | 11 | #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
14 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 12 | enum Repr { |
15 | fmt::Display::fmt(&self.text, f) | 13 | Text(SmolStr), |
16 | } | 14 | TupleField(usize), |
17 | } | 15 | } |
18 | 16 | ||
19 | impl fmt::Debug for Name { | 17 | impl fmt::Display for Name { |
20 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 18 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
21 | fmt::Debug::fmt(&self.text, f) | 19 | match &self.0 { |
20 | Repr::Text(text) => fmt::Display::fmt(&text, f), | ||
21 | Repr::TupleField(idx) => fmt::Display::fmt(&idx, f), | ||
22 | } | ||
22 | } | 23 | } |
23 | } | 24 | } |
24 | 25 | ||
@@ -26,29 +27,38 @@ impl Name { | |||
26 | /// Note: this is private to make creating name from random string hard. | 27 | /// Note: this is private to make creating name from random string hard. |
27 | /// Hopefully, this should allow us to integrate hygiene cleaner in the | 28 | /// Hopefully, this should allow us to integrate hygiene cleaner in the |
28 | /// future, and to switch to interned representation of names. | 29 | /// future, and to switch to interned representation of names. |
29 | const fn new(text: SmolStr) -> Name { | 30 | const fn new_text(text: SmolStr) -> Name { |
30 | Name { text } | 31 | Name(Repr::Text(text)) |
31 | } | 32 | } |
32 | 33 | ||
33 | pub(crate) fn missing() -> Name { | 34 | pub(crate) fn new_tuple_field(idx: usize) -> Name { |
34 | Name::new("[missing name]".into()) | 35 | Name(Repr::TupleField(idx)) |
35 | } | 36 | } |
36 | 37 | ||
37 | pub(crate) fn tuple_field_name(idx: usize) -> Name { | 38 | /// Shortcut to create inline plain text name |
38 | Name::new(idx.to_string().into()) | 39 | const fn new_inline_ascii(len: usize, text: &[u8]) -> Name { |
40 | Name::new_text(SmolStr::new_inline_from_ascii(len, text)) | ||
39 | } | 41 | } |
40 | 42 | ||
41 | // There's should be no way to extract a string out of `Name`: `Name` in the | 43 | /// Resolve a name from the text of token. |
42 | // future, `Name` will include hygiene information, and you can't encode | 44 | fn resolve(raw_text: &SmolStr) -> Name { |
43 | // hygiene into a String. | 45 | let raw_start = "r#"; |
44 | // | 46 | if raw_text.as_str().starts_with(raw_start) { |
45 | // If you need to compare something with `Name`, compare `Name`s directly. | 47 | Name::new_text(SmolStr::new(&raw_text[raw_start.len()..])) |
46 | // | 48 | } else { |
47 | // If you need to render `Name` for the user, use the `Display` impl, but be | 49 | Name::new_text(raw_text.clone()) |
48 | // aware that it strips hygiene info. | 50 | } |
49 | #[deprecated(note = "use to_string instead")] | 51 | } |
50 | pub fn as_smolstr(&self) -> &SmolStr { | 52 | |
51 | &self.text | 53 | pub(crate) fn missing() -> Name { |
54 | Name::new_text("[missing name]".into()) | ||
55 | } | ||
56 | |||
57 | pub(crate) fn as_tuple_index(&self) -> Option<usize> { | ||
58 | match self.0 { | ||
59 | Repr::TupleField(idx) => Some(idx), | ||
60 | _ => None, | ||
61 | } | ||
52 | } | 62 | } |
53 | } | 63 | } |
54 | 64 | ||
@@ -58,15 +68,16 @@ pub(crate) trait AsName { | |||
58 | 68 | ||
59 | impl AsName for ast::NameRef { | 69 | impl AsName for ast::NameRef { |
60 | fn as_name(&self) -> Name { | 70 | fn as_name(&self) -> Name { |
61 | let name = resolve_name(self.text()); | 71 | match self.as_tuple_field() { |
62 | Name::new(name) | 72 | Some(idx) => Name::new_tuple_field(idx), |
73 | None => Name::resolve(self.text()), | ||
74 | } | ||
63 | } | 75 | } |
64 | } | 76 | } |
65 | 77 | ||
66 | impl AsName for ast::Name { | 78 | impl AsName for ast::Name { |
67 | fn as_name(&self) -> Name { | 79 | fn as_name(&self) -> Name { |
68 | let name = resolve_name(self.text()); | 80 | Name::resolve(self.text()) |
69 | Name::new(name) | ||
70 | } | 81 | } |
71 | } | 82 | } |
72 | 83 | ||
@@ -74,66 +85,56 @@ impl AsName for ast::FieldKind { | |||
74 | fn as_name(&self) -> Name { | 85 | fn as_name(&self) -> Name { |
75 | match self { | 86 | match self { |
76 | ast::FieldKind::Name(nr) => nr.as_name(), | 87 | ast::FieldKind::Name(nr) => nr.as_name(), |
77 | ast::FieldKind::Index(idx) => Name::new(idx.text().clone()), | 88 | ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text().parse().unwrap()), |
78 | } | 89 | } |
79 | } | 90 | } |
80 | } | 91 | } |
81 | 92 | ||
82 | impl AsName for ra_db::Dependency { | 93 | impl AsName for ra_db::Dependency { |
83 | fn as_name(&self) -> Name { | 94 | fn as_name(&self) -> Name { |
84 | Name::new(self.name.clone()) | 95 | Name::new_text(self.name.clone()) |
85 | } | 96 | } |
86 | } | 97 | } |
87 | 98 | ||
88 | // Primitives | 99 | // Primitives |
89 | pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize")); | 100 | pub(crate) const ISIZE: Name = Name::new_inline_ascii(5, b"isize"); |
90 | pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8")); | 101 | pub(crate) const I8: Name = Name::new_inline_ascii(2, b"i8"); |
91 | pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16")); | 102 | pub(crate) const I16: Name = Name::new_inline_ascii(3, b"i16"); |
92 | pub(crate) const I32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i32")); | 103 | pub(crate) const I32: Name = Name::new_inline_ascii(3, b"i32"); |
93 | pub(crate) const I64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i64")); | 104 | pub(crate) const I64: Name = Name::new_inline_ascii(3, b"i64"); |
94 | pub(crate) const I128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"i128")); | 105 | pub(crate) const I128: Name = Name::new_inline_ascii(4, b"i128"); |
95 | pub(crate) const USIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"usize")); | 106 | pub(crate) const USIZE: Name = Name::new_inline_ascii(5, b"usize"); |
96 | pub(crate) const U8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"u8")); | 107 | pub(crate) const U8: Name = Name::new_inline_ascii(2, b"u8"); |
97 | pub(crate) const U16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u16")); | 108 | pub(crate) const U16: Name = Name::new_inline_ascii(3, b"u16"); |
98 | pub(crate) const U32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u32")); | 109 | pub(crate) const U32: Name = Name::new_inline_ascii(3, b"u32"); |
99 | pub(crate) const U64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u64")); | 110 | pub(crate) const U64: Name = Name::new_inline_ascii(3, b"u64"); |
100 | pub(crate) const U128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"u128")); | 111 | pub(crate) const U128: Name = Name::new_inline_ascii(4, b"u128"); |
101 | pub(crate) const F32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f32")); | 112 | pub(crate) const F32: Name = Name::new_inline_ascii(3, b"f32"); |
102 | pub(crate) const F64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f64")); | 113 | pub(crate) const F64: Name = Name::new_inline_ascii(3, b"f64"); |
103 | pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool")); | 114 | pub(crate) const BOOL: Name = Name::new_inline_ascii(4, b"bool"); |
104 | pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char")); | 115 | pub(crate) const CHAR: Name = Name::new_inline_ascii(4, b"char"); |
105 | pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str")); | 116 | pub(crate) const STR: Name = Name::new_inline_ascii(3, b"str"); |
106 | 117 | ||
107 | // Special names | 118 | // Special names |
108 | pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self")); | 119 | pub(crate) const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self"); |
109 | pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self")); | 120 | pub(crate) const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self"); |
110 | pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules")); | 121 | pub(crate) const MACRO_RULES: Name = Name::new_inline_ascii(11, b"macro_rules"); |
111 | 122 | ||
112 | // Components of known path (value or mod name) | 123 | // Components of known path (value or mod name) |
113 | pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std")); | 124 | pub(crate) const STD: Name = Name::new_inline_ascii(3, b"std"); |
114 | pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter")); | 125 | pub(crate) const ITER: Name = Name::new_inline_ascii(4, b"iter"); |
115 | pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); | 126 | pub(crate) const OPS: Name = Name::new_inline_ascii(3, b"ops"); |
116 | pub(crate) const FUTURE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); | 127 | pub(crate) const FUTURE: Name = Name::new_inline_ascii(6, b"future"); |
117 | pub(crate) const RESULT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result")); | 128 | pub(crate) const RESULT: Name = Name::new_inline_ascii(6, b"result"); |
118 | pub(crate) const BOXED: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed")); | 129 | pub(crate) const BOXED: Name = Name::new_inline_ascii(5, b"boxed"); |
119 | 130 | ||
120 | // Components of known path (type name) | 131 | // Components of known path (type name) |
121 | pub(crate) const INTO_ITERATOR_TYPE: Name = | 132 | pub(crate) const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator"); |
122 | Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator")); | 133 | pub(crate) const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item"); |
123 | pub(crate) const ITEM_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item")); | 134 | pub(crate) const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try"); |
124 | pub(crate) const TRY_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); | 135 | pub(crate) const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok"); |
125 | pub(crate) const OK_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); | 136 | pub(crate) const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future"); |
126 | pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); | 137 | pub(crate) const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result"); |
127 | pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); | 138 | pub(crate) const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output"); |
128 | pub(crate) const OUTPUT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); | 139 | pub(crate) const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target"); |
129 | pub(crate) const TARGET_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); | 140 | pub(crate) const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); |
130 | pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box")); | ||
131 | |||
132 | fn resolve_name(text: &SmolStr) -> SmolStr { | ||
133 | let raw_start = "r#"; | ||
134 | if text.as_str().starts_with(raw_start) { | ||
135 | SmolStr::new(&text[raw_start.len()..]) | ||
136 | } else { | ||
137 | text.clone() | ||
138 | } | ||
139 | } | ||
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index b808a0c36..67adcfa28 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -332,6 +332,20 @@ impl CrateDefMap { | |||
332 | ) -> ResolvePathResult { | 332 | ) -> ResolvePathResult { |
333 | let mut segments = path.segments.iter().enumerate(); | 333 | let mut segments = path.segments.iter().enumerate(); |
334 | let mut curr_per_ns: PerNs = match path.kind { | 334 | let mut curr_per_ns: PerNs = match path.kind { |
335 | PathKind::DollarCrate(krate) => { | ||
336 | if krate == self.krate { | ||
337 | tested_by!(macro_dollar_crate_self); | ||
338 | PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) | ||
339 | } else { | ||
340 | match krate.root_module(db) { | ||
341 | Some(module) => { | ||
342 | tested_by!(macro_dollar_crate_other); | ||
343 | PerNs::types(module.into()) | ||
344 | } | ||
345 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | ||
346 | } | ||
347 | } | ||
348 | } | ||
335 | PathKind::Crate => { | 349 | PathKind::Crate => { |
336 | PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) | 350 | PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) |
337 | } | 351 | } |
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index ef7dc6ebe..65929c522 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -662,7 +662,10 @@ where | |||
662 | // Case 1: macro rules, define a macro in crate-global mutable scope | 662 | // Case 1: macro rules, define a macro in crate-global mutable scope |
663 | if is_macro_rules(&mac.path) { | 663 | if is_macro_rules(&mac.path) { |
664 | if let Some(name) = &mac.name { | 664 | if let Some(name) = &mac.name { |
665 | let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id)); | 665 | let macro_id = MacroDefId { |
666 | ast_id: mac.ast_id.with_file_id(self.file_id), | ||
667 | krate: self.def_collector.def_map.krate, | ||
668 | }; | ||
666 | let macro_ = MacroDef { id: macro_id }; | 669 | let macro_ = MacroDef { id: macro_id }; |
667 | self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export); | 670 | self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export); |
668 | } | 671 | } |
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index 29aaddbf1..c494b95b0 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs | |||
@@ -9,7 +9,7 @@ use test_utils::tested_by; | |||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::{AstDatabase, DefDatabase}, | 11 | db::{AstDatabase, DefDatabase}, |
12 | AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, | 12 | AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | /// `RawItems` is a set of top-level items in a file (except for impls). | 15 | /// `RawItems` is a set of top-level items in a file (except for impls). |
@@ -71,6 +71,8 @@ impl RawItems { | |||
71 | raw_items: RawItems::default(), | 71 | raw_items: RawItems::default(), |
72 | source_ast_id_map: db.ast_id_map(file_id), | 72 | source_ast_id_map: db.ast_id_map(file_id), |
73 | source_map: ImportSourceMap::default(), | 73 | source_map: ImportSourceMap::default(), |
74 | file_id, | ||
75 | db, | ||
74 | }; | 76 | }; |
75 | if let Some(node) = db.parse_or_expand(file_id) { | 77 | if let Some(node) = db.parse_or_expand(file_id) { |
76 | if let Some(source_file) = ast::SourceFile::cast(node.clone()) { | 78 | if let Some(source_file) = ast::SourceFile::cast(node.clone()) { |
@@ -192,13 +194,15 @@ pub(super) struct MacroData { | |||
192 | pub(super) export: bool, | 194 | pub(super) export: bool, |
193 | } | 195 | } |
194 | 196 | ||
195 | struct RawItemsCollector { | 197 | struct RawItemsCollector<DB> { |
196 | raw_items: RawItems, | 198 | raw_items: RawItems, |
197 | source_ast_id_map: Arc<AstIdMap>, | 199 | source_ast_id_map: Arc<AstIdMap>, |
198 | source_map: ImportSourceMap, | 200 | source_map: ImportSourceMap, |
201 | file_id: HirFileId, | ||
202 | db: DB, | ||
199 | } | 203 | } |
200 | 204 | ||
201 | impl RawItemsCollector { | 205 | impl<DB: AstDatabase> RawItemsCollector<&DB> { |
202 | fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { | 206 | fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { |
203 | for item_or_macro in body.items_with_macros() { | 207 | for item_or_macro in body.items_with_macros() { |
204 | match item_or_macro { | 208 | match item_or_macro { |
@@ -300,17 +304,21 @@ impl RawItemsCollector { | |||
300 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { | 304 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { |
301 | let is_prelude = use_item.has_atom_attr("prelude_import"); | 305 | let is_prelude = use_item.has_atom_attr("prelude_import"); |
302 | 306 | ||
303 | Path::expand_use_item(&use_item, |path, use_tree, is_glob, alias| { | 307 | Path::expand_use_item( |
304 | let import_data = ImportData { | 308 | Source { ast: use_item, file_id: self.file_id }, |
305 | path, | 309 | self.db, |
306 | alias, | 310 | |path, use_tree, is_glob, alias| { |
307 | is_glob, | 311 | let import_data = ImportData { |
308 | is_prelude, | 312 | path, |
309 | is_extern_crate: false, | 313 | alias, |
310 | is_macro_use: false, | 314 | is_glob, |
311 | }; | 315 | is_prelude, |
312 | self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree))); | 316 | is_extern_crate: false, |
313 | }) | 317 | is_macro_use: false, |
318 | }; | ||
319 | self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree))); | ||
320 | }, | ||
321 | ) | ||
314 | } | 322 | } |
315 | 323 | ||
316 | fn add_extern_crate_item( | 324 | fn add_extern_crate_item( |
@@ -335,7 +343,10 @@ impl RawItemsCollector { | |||
335 | } | 343 | } |
336 | 344 | ||
337 | fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { | 345 | fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { |
338 | let path = match m.path().and_then(Path::from_ast) { | 346 | let path = match m |
347 | .path() | ||
348 | .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db)) | ||
349 | { | ||
339 | Some(it) => it, | 350 | Some(it) => it, |
340 | _ => return, | 351 | _ => return, |
341 | }; | 352 | }; |
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index bd60f4258..e4b408394 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs | |||
@@ -515,3 +515,108 @@ fn path_qualified_macros() { | |||
515 | â‹®not_found: _ | 515 | â‹®not_found: _ |
516 | "###); | 516 | "###); |
517 | } | 517 | } |
518 | |||
519 | #[test] | ||
520 | fn macro_dollar_crate_is_correct_in_item() { | ||
521 | covers!(macro_dollar_crate_self); | ||
522 | covers!(macro_dollar_crate_other); | ||
523 | let map = def_map_with_crate_graph( | ||
524 | " | ||
525 | //- /main.rs | ||
526 | #[macro_use] | ||
527 | extern crate foo; | ||
528 | |||
529 | #[macro_use] | ||
530 | mod m { | ||
531 | macro_rules! current { | ||
532 | () => { | ||
533 | use $crate::Foo as FooSelf; | ||
534 | } | ||
535 | } | ||
536 | } | ||
537 | |||
538 | struct Foo; | ||
539 | |||
540 | current!(); | ||
541 | not_current1!(); | ||
542 | foo::not_current2!(); | ||
543 | |||
544 | //- /lib.rs | ||
545 | mod m { | ||
546 | #[macro_export] | ||
547 | macro_rules! not_current1 { | ||
548 | () => { | ||
549 | use $crate::Bar; | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | |||
554 | #[macro_export] | ||
555 | macro_rules! not_current2 { | ||
556 | () => { | ||
557 | use $crate::Baz; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | struct Bar; | ||
562 | struct Baz; | ||
563 | ", | ||
564 | crate_graph! { | ||
565 | "main": ("/main.rs", ["foo"]), | ||
566 | "foo": ("/lib.rs", []), | ||
567 | }, | ||
568 | ); | ||
569 | assert_snapshot!(map, @r###" | ||
570 | â‹®crate | ||
571 | â‹®Bar: t v | ||
572 | â‹®Baz: t v | ||
573 | â‹®Foo: t v | ||
574 | â‹®FooSelf: t v | ||
575 | â‹®foo: t | ||
576 | â‹®m: t | ||
577 | â‹® | ||
578 | â‹®crate::m | ||
579 | "###); | ||
580 | } | ||
581 | |||
582 | #[test] | ||
583 | fn macro_dollar_crate_is_correct_in_indirect_deps() { | ||
584 | covers!(macro_dollar_crate_other); | ||
585 | // From std | ||
586 | let map = def_map_with_crate_graph( | ||
587 | r#" | ||
588 | //- /main.rs | ||
589 | foo!(); | ||
590 | |||
591 | //- /std.rs | ||
592 | #[prelude_import] | ||
593 | use self::prelude::*; | ||
594 | |||
595 | pub use core::foo; | ||
596 | |||
597 | mod prelude {} | ||
598 | |||
599 | #[macro_use] | ||
600 | mod std_macros; | ||
601 | |||
602 | //- /core.rs | ||
603 | #[macro_export] | ||
604 | macro_rules! foo { | ||
605 | () => { | ||
606 | use $crate::bar; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | pub struct bar; | ||
611 | "#, | ||
612 | crate_graph! { | ||
613 | "main": ("/main.rs", ["std"]), | ||
614 | "std": ("/std.rs", ["core"]), | ||
615 | "core": ("/core.rs", []), | ||
616 | }, | ||
617 | ); | ||
618 | assert_snapshot!(map, @r###" | ||
619 | â‹®crate | ||
620 | â‹®bar: t v | ||
621 | "###); | ||
622 | } | ||
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 39d1b7e46..158c853d4 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs | |||
@@ -5,7 +5,7 @@ use ra_syntax::{ | |||
5 | AstNode, | 5 | AstNode, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::{name, type_ref::TypeRef, AsName, Name}; | 8 | use crate::{db::AstDatabase, name, type_ref::TypeRef, AsName, Crate, Name, Source}; |
9 | 9 | ||
10 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 10 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
11 | pub struct Path { | 11 | pub struct Path { |
@@ -52,16 +52,19 @@ pub enum PathKind { | |||
52 | Abs, | 52 | Abs, |
53 | // Type based path like `<T>::foo` | 53 | // Type based path like `<T>::foo` |
54 | Type(Box<TypeRef>), | 54 | Type(Box<TypeRef>), |
55 | // `$crate` from macro expansion | ||
56 | DollarCrate(Crate), | ||
55 | } | 57 | } |
56 | 58 | ||
57 | impl Path { | 59 | impl Path { |
58 | /// Calls `cb` with all paths, represented by this use item. | 60 | /// Calls `cb` with all paths, represented by this use item. |
59 | pub fn expand_use_item( | 61 | pub fn expand_use_item( |
60 | item: &ast::UseItem, | 62 | item_src: Source<ast::UseItem>, |
63 | db: &impl AstDatabase, | ||
61 | mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), | 64 | mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), |
62 | ) { | 65 | ) { |
63 | if let Some(tree) = item.use_tree() { | 66 | if let Some(tree) = item_src.ast.use_tree() { |
64 | expand_use_tree(None, tree, &mut cb); | 67 | expand_use_tree(None, tree, &|| item_src.file_id.macro_crate(db), &mut cb); |
65 | } | 68 | } |
66 | } | 69 | } |
67 | 70 | ||
@@ -76,7 +79,19 @@ impl Path { | |||
76 | } | 79 | } |
77 | 80 | ||
78 | /// Converts an `ast::Path` to `Path`. Works with use trees. | 81 | /// Converts an `ast::Path` to `Path`. Works with use trees. |
79 | pub fn from_ast(mut path: ast::Path) -> Option<Path> { | 82 | /// DEPRECATED: It does not handle `$crate` from macro call. |
83 | pub fn from_ast(path: ast::Path) -> Option<Path> { | ||
84 | Path::parse(path, &|| None) | ||
85 | } | ||
86 | |||
87 | /// Converts an `ast::Path` to `Path`. Works with use trees. | ||
88 | /// It correctly handles `$crate` based path from macro call. | ||
89 | pub fn from_src(source: Source<ast::Path>, db: &impl AstDatabase) -> Option<Path> { | ||
90 | let file_id = source.file_id; | ||
91 | Path::parse(source.ast, &|| file_id.macro_crate(db)) | ||
92 | } | ||
93 | |||
94 | fn parse(mut path: ast::Path, macro_crate: &impl Fn() -> Option<Crate>) -> Option<Path> { | ||
80 | let mut kind = PathKind::Plain; | 95 | let mut kind = PathKind::Plain; |
81 | let mut segments = Vec::new(); | 96 | let mut segments = Vec::new(); |
82 | loop { | 97 | loop { |
@@ -88,6 +103,13 @@ impl Path { | |||
88 | 103 | ||
89 | match segment.kind()? { | 104 | match segment.kind()? { |
90 | ast::PathSegmentKind::Name(name) => { | 105 | ast::PathSegmentKind::Name(name) => { |
106 | if name.text() == "$crate" { | ||
107 | if let Some(macro_crate) = macro_crate() { | ||
108 | kind = PathKind::DollarCrate(macro_crate); | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | |||
91 | let args = segment | 113 | let args = segment |
92 | .type_arg_list() | 114 | .type_arg_list() |
93 | .and_then(GenericArgs::from_ast) | 115 | .and_then(GenericArgs::from_ast) |
@@ -113,7 +135,7 @@ impl Path { | |||
113 | } | 135 | } |
114 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo | 136 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo |
115 | Some(trait_ref) => { | 137 | Some(trait_ref) => { |
116 | let path = Path::from_ast(trait_ref.path()?)?; | 138 | let path = Path::parse(trait_ref.path()?, macro_crate)?; |
117 | kind = path.kind; | 139 | kind = path.kind; |
118 | let mut prefix_segments = path.segments; | 140 | let mut prefix_segments = path.segments; |
119 | prefix_segments.reverse(); | 141 | prefix_segments.reverse(); |
@@ -264,6 +286,7 @@ impl From<Name> for Path { | |||
264 | fn expand_use_tree( | 286 | fn expand_use_tree( |
265 | prefix: Option<Path>, | 287 | prefix: Option<Path>, |
266 | tree: ast::UseTree, | 288 | tree: ast::UseTree, |
289 | macro_crate: &impl Fn() -> Option<Crate>, | ||
267 | cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>), | 290 | cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>), |
268 | ) { | 291 | ) { |
269 | if let Some(use_tree_list) = tree.use_tree_list() { | 292 | if let Some(use_tree_list) = tree.use_tree_list() { |
@@ -272,13 +295,13 @@ fn expand_use_tree( | |||
272 | None => prefix, | 295 | None => prefix, |
273 | // E.g. `use something::{inner}` (prefix is `None`, path is `something`) | 296 | // E.g. `use something::{inner}` (prefix is `None`, path is `something`) |
274 | // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) | 297 | // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) |
275 | Some(path) => match convert_path(prefix, path) { | 298 | Some(path) => match convert_path(prefix, path, macro_crate) { |
276 | Some(it) => Some(it), | 299 | Some(it) => Some(it), |
277 | None => return, // FIXME: report errors somewhere | 300 | None => return, // FIXME: report errors somewhere |
278 | }, | 301 | }, |
279 | }; | 302 | }; |
280 | for child_tree in use_tree_list.use_trees() { | 303 | for child_tree in use_tree_list.use_trees() { |
281 | expand_use_tree(prefix.clone(), child_tree, cb); | 304 | expand_use_tree(prefix.clone(), child_tree, macro_crate, cb); |
282 | } | 305 | } |
283 | } else { | 306 | } else { |
284 | let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); | 307 | let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); |
@@ -295,7 +318,7 @@ fn expand_use_tree( | |||
295 | } | 318 | } |
296 | } | 319 | } |
297 | } | 320 | } |
298 | if let Some(path) = convert_path(prefix, ast_path) { | 321 | if let Some(path) = convert_path(prefix, ast_path, macro_crate) { |
299 | let is_glob = tree.has_star(); | 322 | let is_glob = tree.has_star(); |
300 | cb(path, &tree, is_glob, alias) | 323 | cb(path, &tree, is_glob, alias) |
301 | } | 324 | } |
@@ -305,12 +328,29 @@ fn expand_use_tree( | |||
305 | } | 328 | } |
306 | } | 329 | } |
307 | 330 | ||
308 | fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> { | 331 | fn convert_path( |
309 | let prefix = | 332 | prefix: Option<Path>, |
310 | if let Some(qual) = path.qualifier() { Some(convert_path(prefix, qual)?) } else { prefix }; | 333 | path: ast::Path, |
334 | macro_crate: &impl Fn() -> Option<Crate>, | ||
335 | ) -> Option<Path> { | ||
336 | let prefix = if let Some(qual) = path.qualifier() { | ||
337 | Some(convert_path(prefix, qual, macro_crate)?) | ||
338 | } else { | ||
339 | prefix | ||
340 | }; | ||
341 | |||
311 | let segment = path.segment()?; | 342 | let segment = path.segment()?; |
312 | let res = match segment.kind()? { | 343 | let res = match segment.kind()? { |
313 | ast::PathSegmentKind::Name(name) => { | 344 | ast::PathSegmentKind::Name(name) => { |
345 | if name.text() == "$crate" { | ||
346 | if let Some(krate) = macro_crate() { | ||
347 | return Some(Path::from_simple_segments( | ||
348 | PathKind::DollarCrate(krate), | ||
349 | iter::empty(), | ||
350 | )); | ||
351 | } | ||
352 | } | ||
353 | |||
314 | // no type args in use | 354 | // no type args in use |
315 | let mut res = prefix | 355 | let mut res = prefix |
316 | .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); | 356 | .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index bd4be8430..6e89bfc76 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -203,6 +203,7 @@ impl SourceAnalyzer { | |||
203 | db: &impl HirDatabase, | 203 | db: &impl HirDatabase, |
204 | macro_call: &ast::MacroCall, | 204 | macro_call: &ast::MacroCall, |
205 | ) -> Option<MacroDef> { | 205 | ) -> Option<MacroDef> { |
206 | // This must be a normal source file rather than macro file. | ||
206 | let path = macro_call.path().and_then(Path::from_ast)?; | 207 | let path = macro_call.path().and_then(Path::from_ast)?; |
207 | self.resolver.resolve_path_as_macro(db, &path) | 208 | self.resolver.resolve_path_as_macro(db, &path) |
208 | } | 209 | } |
@@ -261,6 +262,7 @@ impl SourceAnalyzer { | |||
261 | return Some(PathResolution::AssocItem(assoc)); | 262 | return Some(PathResolution::AssocItem(assoc)); |
262 | } | 263 | } |
263 | } | 264 | } |
265 | // This must be a normal source file rather than macro file. | ||
264 | let hir_path = crate::Path::from_ast(path.clone())?; | 266 | let hir_path = crate::Path::from_ast(path.clone())?; |
265 | self.resolve_hir_path(db, &hir_path) | 267 | self.resolve_hir_path(db, &hir_path) |
266 | } | 268 | } |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 8e07fc186..2e4a489a0 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -609,7 +609,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
609 | 609 | ||
610 | for (i, &subpat) in subpats.iter().enumerate() { | 610 | for (i, &subpat) in subpats.iter().enumerate() { |
611 | let expected_ty = def | 611 | let expected_ty = def |
612 | .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) | 612 | .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) |
613 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 613 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
614 | .subst(&substs); | 614 | .subst(&substs); |
615 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 615 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
@@ -1374,10 +1374,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1374 | ) | 1374 | ) |
1375 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { | 1375 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
1376 | Ty::Apply(a_ty) => match a_ty.ctor { | 1376 | Ty::Apply(a_ty) => match a_ty.ctor { |
1377 | TypeCtor::Tuple { .. } => { | 1377 | TypeCtor::Tuple { .. } => name |
1378 | let i = name.to_string().parse::<usize>().ok(); | 1378 | .as_tuple_index() |
1379 | i.and_then(|i| a_ty.parameters.0.get(i).cloned()) | 1379 | .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), |
1380 | } | ||
1381 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { | 1380 | TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { |
1382 | self.write_field_resolution(tgt_expr, field); | 1381 | self.write_field_resolution(tgt_expr, field); |
1383 | field.ty(self.db).subst(&a_ty.parameters) | 1382 | field.ty(self.db).subst(&a_ty.parameters) |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 7de434180..4df39c191 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -3130,6 +3130,39 @@ fn test() { S.foo()<|>; } | |||
3130 | assert_eq!(t, "u128"); | 3130 | assert_eq!(t, "u128"); |
3131 | } | 3131 | } |
3132 | 3132 | ||
3133 | #[test] | ||
3134 | fn infer_macro_with_dollar_crate_is_correct_in_expr() { | ||
3135 | covers!(macro_dollar_crate_other); | ||
3136 | let (mut db, pos) = MockDatabase::with_position( | ||
3137 | r#" | ||
3138 | //- /main.rs | ||
3139 | fn test() { | ||
3140 | let x = (foo::foo!(1), foo::foo!(2)); | ||
3141 | x<|>; | ||
3142 | } | ||
3143 | |||
3144 | //- /lib.rs | ||
3145 | #[macro_export] | ||
3146 | macro_rules! foo { | ||
3147 | (1) => { $crate::bar!() }; | ||
3148 | (2) => { 1 + $crate::baz() }; | ||
3149 | } | ||
3150 | |||
3151 | #[macro_export] | ||
3152 | macro_rules! bar { | ||
3153 | () => { 42 } | ||
3154 | } | ||
3155 | |||
3156 | pub fn baz() -> usize { 31usize } | ||
3157 | "#, | ||
3158 | ); | ||
3159 | db.set_crate_graph_from_fixture(crate_graph! { | ||
3160 | "main": ("/main.rs", ["foo"]), | ||
3161 | "foo": ("/lib.rs", []), | ||
3162 | }); | ||
3163 | assert_eq!("(i32, usize)", type_at_pos(&db, pos)); | ||
3164 | } | ||
3165 | |||
3133 | #[ignore] | 3166 | #[ignore] |
3134 | #[test] | 3167 | #[test] |
3135 | fn method_resolution_trait_before_autoref() { | 3168 | fn method_resolution_trait_before_autoref() { |
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs index bc8acc7ee..2cf06b250 100644 --- a/crates/ra_hir/src/type_ref.rs +++ b/crates/ra_hir/src/type_ref.rs | |||
@@ -72,6 +72,7 @@ impl TypeRef { | |||
72 | } | 72 | } |
73 | ast::TypeRef::NeverType(..) => TypeRef::Never, | 73 | ast::TypeRef::NeverType(..) => TypeRef::Never, |
74 | ast::TypeRef::PathType(inner) => { | 74 | ast::TypeRef::PathType(inner) => { |
75 | // FIXME: Use `Path::from_src` | ||
75 | inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error) | 76 | inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error) |
76 | } | 77 | } |
77 | ast::TypeRef::PointerType(inner) => { | 78 | ast::TypeRef::PointerType(inner) => { |
@@ -141,6 +142,7 @@ impl TypeBound { | |||
141 | Some(p) => p, | 142 | Some(p) => p, |
142 | None => return TypeBound::Error, | 143 | None => return TypeBound::Error, |
143 | }; | 144 | }; |
145 | // FIXME: Use `Path::from_src` | ||
144 | let path = match Path::from_ast(path) { | 146 | let path = match Path::from_ast(path) { |
145 | Some(p) => p, | 147 | Some(p) => p, |
146 | None => return TypeBound::Error, | 148 | None => return TypeBound::Error, |