aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/attr.rs6
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/nameres.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs14
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs24
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs12
-rw-r--r--crates/ra_hir_def/src/path.rs345
-rw-r--r--crates/ra_hir_def/src/path/lower.rs176
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs (renamed from crates/ra_hir_def/src/path/lower_use.rs)23
-rw-r--r--crates/ra_hir_def/src/resolver.rs46
10 files changed, 385 insertions, 267 deletions
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 5bf82e191..9efa4970c 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -12,7 +12,7 @@ use ra_syntax::{
12use tt::Subtree; 12use tt::Subtree;
13 13
14use crate::{ 14use crate::{
15 db::DefDatabase, path::Path, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup, 15 db::DefDatabase, path::ModPath, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup,
16}; 16};
17 17
18#[derive(Default, Debug, Clone, PartialEq, Eq)] 18#[derive(Default, Debug, Clone, PartialEq, Eq)]
@@ -94,7 +94,7 @@ impl Attrs {
94 94
95#[derive(Debug, Clone, PartialEq, Eq)] 95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct Attr { 96pub struct Attr {
97 pub(crate) path: Path, 97 pub(crate) path: ModPath,
98 pub(crate) input: Option<AttrInput>, 98 pub(crate) input: Option<AttrInput>,
99} 99}
100 100
@@ -106,7 +106,7 @@ pub enum AttrInput {
106 106
107impl Attr { 107impl Attr {
108 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { 108 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
109 let path = Path::from_src(ast.path()?, hygiene)?; 109 let path = ModPath::from_src(ast.path()?, hygiene)?;
110 let input = match ast.input() { 110 let input = match ast.input() {
111 None => None, 111 None => None,
112 Some(ast::AttrInput::Literal(lit)) => { 112 Some(ast::AttrInput::Literal(lit)) => {
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index b3bc336cf..7787cb87f 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -83,7 +83,7 @@ impl Expander {
83 83
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
85 self.crate_def_map 85 self.crate_def_map
86 .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) 86 .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other)
87 .0 87 .0
88 .take_macros() 88 .take_macros()
89 } 89 }
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index bd237a7b3..9aae7e48e 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -74,7 +74,7 @@ use crate::{
74 builtin_type::BuiltinType, 74 builtin_type::BuiltinType,
75 db::DefDatabase, 75 db::DefDatabase,
76 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, 76 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
77 path::Path, 77 path::ModPath,
78 per_ns::PerNs, 78 per_ns::PerNs,
79 AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, 79 AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
80}; 80};
@@ -329,7 +329,7 @@ impl CrateDefMap {
329 &self, 329 &self,
330 db: &impl DefDatabase, 330 db: &impl DefDatabase,
331 original_module: LocalModuleId, 331 original_module: LocalModuleId,
332 path: &Path, 332 path: &ModPath,
333 shadow: BuiltinShadowMode, 333 shadow: BuiltinShadowMode,
334 ) -> (PerNs, Option<usize>) { 334 ) -> (PerNs, Option<usize>) {
335 let res = 335 let res =
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 5d7469a6e..912a073ea 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -22,7 +22,7 @@ use crate::{
22 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 22 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
23 raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode, 23 raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode,
24 }, 24 },
25 path::{Path, PathKind}, 25 path::{ModPath, PathKind},
26 per_ns::PerNs, 26 per_ns::PerNs,
27 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, 27 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
28 LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, 28 LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc,
@@ -101,7 +101,7 @@ struct ImportDirective {
101struct MacroDirective { 101struct MacroDirective {
102 module_id: LocalModuleId, 102 module_id: LocalModuleId,
103 ast_id: AstId<ast::MacroCall>, 103 ast_id: AstId<ast::MacroCall>,
104 path: Path, 104 path: ModPath,
105 legacy: Option<MacroCallId>, 105 legacy: Option<MacroCallId>,
106} 106}
107 107
@@ -113,7 +113,7 @@ struct DefCollector<'a, DB> {
113 unresolved_imports: Vec<ImportDirective>, 113 unresolved_imports: Vec<ImportDirective>,
114 resolved_imports: Vec<ImportDirective>, 114 resolved_imports: Vec<ImportDirective>,
115 unexpanded_macros: Vec<MacroDirective>, 115 unexpanded_macros: Vec<MacroDirective>,
116 unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, Path)>, 116 unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>,
117 mod_dirs: FxHashMap<LocalModuleId, ModDir>, 117 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
118 cfg_options: &'a CfgOptions, 118 cfg_options: &'a CfgOptions,
119} 119}
@@ -428,7 +428,7 @@ where
428 } else { 428 } else {
429 match import.path.segments.last() { 429 match import.path.segments.last() {
430 Some(last_segment) => { 430 Some(last_segment) => {
431 let name = import.alias.clone().unwrap_or_else(|| last_segment.name.clone()); 431 let name = import.alias.clone().unwrap_or_else(|| last_segment.clone());
432 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); 432 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
433 433
434 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 434 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
@@ -565,7 +565,7 @@ where
565 res 565 res
566 } 566 }
567 567
568 fn resolve_attribute_macro(&self, path: &Path) -> Option<MacroDefId> { 568 fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
569 // FIXME this is currently super hacky, just enough to support the 569 // FIXME this is currently super hacky, just enough to support the
570 // built-in derives 570 // built-in derives
571 if let Some(name) = path.as_ident() { 571 if let Some(name) = path.as_ident() {
@@ -829,7 +829,7 @@ where
829 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok 829 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
830 _ => continue, // anything else would be an error (which we currently ignore) 830 _ => continue, // anything else would be an error (which we currently ignore)
831 }; 831 };
832 let path = Path::from_tt_ident(ident); 832 let path = ModPath::from_tt_ident(ident);
833 833
834 let ast_id = AstId::new(self.file_id, def.kind.ast_id()); 834 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
835 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path)); 835 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
@@ -917,7 +917,7 @@ where
917 } 917 }
918} 918}
919 919
920fn is_macro_rules(path: &Path) -> bool { 920fn is_macro_rules(path: &ModPath) -> bool {
921 path.as_ident() == Some(&name![macro_rules]) 921 path.as_ident() == Some(&name![macro_rules])
922} 922}
923 923
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index aab4b1dd9..4a249e7e7 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -17,7 +17,7 @@ use test_utils::tested_by;
17use crate::{ 17use crate::{
18 db::DefDatabase, 18 db::DefDatabase,
19 nameres::{BuiltinShadowMode, CrateDefMap}, 19 nameres::{BuiltinShadowMode, CrateDefMap},
20 path::{Path, PathKind}, 20 path::{ModPath, PathKind},
21 per_ns::PerNs, 21 per_ns::PerNs,
22 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, 22 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
23}; 23};
@@ -69,7 +69,7 @@ impl CrateDefMap {
69 db: &impl DefDatabase, 69 db: &impl DefDatabase,
70 mode: ResolveMode, 70 mode: ResolveMode,
71 original_module: LocalModuleId, 71 original_module: LocalModuleId,
72 path: &Path, 72 path: &ModPath,
73 shadow: BuiltinShadowMode, 73 shadow: BuiltinShadowMode,
74 ) -> ResolvePathResult { 74 ) -> ResolvePathResult {
75 // if it is not the last segment, we prefer the module to the builtin 75 // if it is not the last segment, we prefer the module to the builtin
@@ -113,7 +113,7 @@ impl CrateDefMap {
113 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 113 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
114 }; 114 };
115 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 115 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
116 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name, prefer_module(idx)) 116 self.resolve_name_in_crate_root_or_extern_prelude(&segment, prefer_module(idx))
117 } 117 }
118 PathKind::Plain => { 118 PathKind::Plain => {
119 let (idx, segment) = match segments.next() { 119 let (idx, segment) = match segments.next() {
@@ -121,7 +121,7 @@ impl CrateDefMap {
121 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 121 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
122 }; 122 };
123 log::debug!("resolving {:?} in module", segment); 123 log::debug!("resolving {:?} in module", segment);
124 self.resolve_name_in_module(db, original_module, &segment.name, prefer_module(idx)) 124 self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx))
125 } 125 }
126 PathKind::Super => { 126 PathKind::Super => {
127 if let Some(p) = self.modules[original_module].parent { 127 if let Some(p) = self.modules[original_module].parent {
@@ -137,7 +137,7 @@ impl CrateDefMap {
137 Some((_, segment)) => segment, 137 Some((_, segment)) => segment,
138 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 138 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
139 }; 139 };
140 if let Some(def) = self.extern_prelude.get(&segment.name) { 140 if let Some(def) = self.extern_prelude.get(&segment) {
141 log::debug!("absolute path {:?} resolved to crate {:?}", path, def); 141 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
142 PerNs::types(*def) 142 PerNs::types(*def)
143 } else { 143 } else {
@@ -168,8 +168,10 @@ impl CrateDefMap {
168 curr_per_ns = match curr { 168 curr_per_ns = match curr {
169 ModuleDefId::ModuleId(module) => { 169 ModuleDefId::ModuleId(module) => {
170 if module.krate != self.krate { 170 if module.krate != self.krate {
171 let path = 171 let path = ModPath {
172 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; 172 segments: path.segments[i..].to_vec(),
173 kind: PathKind::Self_,
174 };
173 log::debug!("resolving {:?} in other crate", path); 175 log::debug!("resolving {:?} in other crate", path);
174 let defp_map = db.crate_def_map(module.krate); 176 let defp_map = db.crate_def_map(module.krate);
175 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); 177 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
@@ -182,10 +184,10 @@ impl CrateDefMap {
182 } 184 }
183 185
184 // Since it is a qualified path here, it should not contains legacy macros 186 // Since it is a qualified path here, it should not contains legacy macros
185 match self[module.local_id].scope.get(&segment.name, prefer_module(i)) { 187 match self[module.local_id].scope.get(&segment, prefer_module(i)) {
186 Some(res) => res.def, 188 Some(res) => res.def,
187 _ => { 189 _ => {
188 log::debug!("path segment {:?} not found", segment.name); 190 log::debug!("path segment {:?} not found", segment);
189 return ResolvePathResult::empty(ReachedFixedPoint::No); 191 return ResolvePathResult::empty(ReachedFixedPoint::No);
190 } 192 }
191 } 193 }
@@ -194,7 +196,7 @@ impl CrateDefMap {
194 // enum variant 196 // enum variant
195 tested_by!(can_import_enum_variant); 197 tested_by!(can_import_enum_variant);
196 let enum_data = db.enum_data(e); 198 let enum_data = db.enum_data(e);
197 match enum_data.variant(&segment.name) { 199 match enum_data.variant(&segment) {
198 Some(local_id) => { 200 Some(local_id) => {
199 let variant = EnumVariantId { parent: e, local_id }; 201 let variant = EnumVariantId { parent: e, local_id };
200 PerNs::both(variant.into(), variant.into()) 202 PerNs::both(variant.into(), variant.into())
@@ -214,7 +216,7 @@ impl CrateDefMap {
214 // (`Struct::method`), or some other kind of associated item 216 // (`Struct::method`), or some other kind of associated item
215 log::debug!( 217 log::debug!(
216 "path segment {:?} resolved to non-module {:?}, but is not last", 218 "path segment {:?} resolved to non-module {:?}, but is not last",
217 segment.name, 219 segment,
218 curr, 220 curr,
219 ); 221 );
220 222
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index a2821e1c3..ecb4d7c03 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -22,7 +22,7 @@ use ra_syntax::{
22use test_utils::tested_by; 22use test_utils::tested_by;
23 23
24use crate::{ 24use crate::{
25 attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, InFile, 25 attr::Attrs, db::DefDatabase, path::ModPath, trace::Trace, FileAstId, HirFileId, InFile,
26 LocalImportId, 26 LocalImportId,
27}; 27};
28 28
@@ -154,7 +154,7 @@ pub(super) enum ModuleData {
154 154
155#[derive(Debug, Clone, PartialEq, Eq)] 155#[derive(Debug, Clone, PartialEq, Eq)]
156pub struct ImportData { 156pub struct ImportData {
157 pub(super) path: Path, 157 pub(super) path: ModPath,
158 pub(super) alias: Option<Name>, 158 pub(super) alias: Option<Name>,
159 pub(super) is_glob: bool, 159 pub(super) is_glob: bool,
160 pub(super) is_prelude: bool, 160 pub(super) is_prelude: bool,
@@ -206,7 +206,7 @@ impl_arena_id!(Macro);
206#[derive(Debug, PartialEq, Eq)] 206#[derive(Debug, PartialEq, Eq)]
207pub(super) struct MacroData { 207pub(super) struct MacroData {
208 pub(super) ast_id: FileAstId<ast::MacroCall>, 208 pub(super) ast_id: FileAstId<ast::MacroCall>,
209 pub(super) path: Path, 209 pub(super) path: ModPath,
210 pub(super) name: Option<Name>, 210 pub(super) name: Option<Name>,
211 pub(super) export: bool, 211 pub(super) export: bool,
212 pub(super) builtin: bool, 212 pub(super) builtin: bool,
@@ -327,7 +327,7 @@ impl RawItemsCollector {
327 let attrs = self.parse_attrs(&use_item); 327 let attrs = self.parse_attrs(&use_item);
328 328
329 let mut buf = Vec::new(); 329 let mut buf = Vec::new();
330 Path::expand_use_item( 330 ModPath::expand_use_item(
331 InFile { value: use_item, file_id: self.file_id }, 331 InFile { value: use_item, file_id: self.file_id },
332 &self.hygiene, 332 &self.hygiene,
333 |path, use_tree, is_glob, alias| { 333 |path, use_tree, is_glob, alias| {
@@ -353,7 +353,7 @@ impl RawItemsCollector {
353 extern_crate: ast::ExternCrateItem, 353 extern_crate: ast::ExternCrateItem,
354 ) { 354 ) {
355 if let Some(name_ref) = extern_crate.name_ref() { 355 if let Some(name_ref) = extern_crate.name_ref() {
356 let path = Path::from_name_ref(&name_ref); 356 let path = ModPath::from_name_ref(&name_ref);
357 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); 357 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name());
358 let attrs = self.parse_attrs(&extern_crate); 358 let attrs = self.parse_attrs(&extern_crate);
359 // FIXME: cfg_attr 359 // FIXME: cfg_attr
@@ -377,7 +377,7 @@ impl RawItemsCollector {
377 377
378 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { 378 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
379 let attrs = self.parse_attrs(&m); 379 let attrs = self.parse_attrs(&m);
380 let path = match m.path().and_then(|path| Path::from_src(path, &self.hygiene)) { 380 let path = match m.path().and_then(|path| ModPath::from_src(path, &self.hygiene)) {
381 Some(it) => it, 381 Some(it) => it,
382 _ => return, 382 _ => return,
383 }; 383 };
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 1e9eb14ea..20d6d98ea 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -1,31 +1,78 @@
1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`. 1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
2mod lower_use; 2mod lower;
3 3
4use std::{iter, sync::Arc}; 4use std::{iter, sync::Arc};
5 5
6use either::Either;
7use hir_expand::{ 6use hir_expand::{
8 hygiene::Hygiene, 7 hygiene::Hygiene,
9 name::{name, AsName, Name}, 8 name::{AsName, Name},
10}; 9};
11use ra_db::CrateId; 10use ra_db::CrateId;
12use ra_syntax::{ 11use ra_syntax::ast;
13 ast::{self, TypeAscriptionOwner},
14 AstNode,
15};
16 12
17use crate::{type_ref::TypeRef, InFile}; 13use crate::{type_ref::TypeRef, InFile};
18 14
19#[derive(Debug, Clone, PartialEq, Eq, Hash)] 15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct Path { 16pub struct ModPath {
21 pub kind: PathKind, 17 pub kind: PathKind,
22 pub segments: Vec<PathSegment>, 18 pub segments: Vec<Name>,
19}
20
21impl ModPath {
22 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
23 lower::lower_path(path, hygiene).map(|it| it.mod_path)
24 }
25
26 pub fn from_simple_segments(
27 kind: PathKind,
28 segments: impl IntoIterator<Item = Name>,
29 ) -> ModPath {
30 let segments = segments.into_iter().collect::<Vec<_>>();
31 ModPath { kind, segments }
32 }
33
34 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath {
35 name_ref.as_name().into()
36 }
37
38 /// Converts an `tt::Ident` into a single-identifier `Path`.
39 pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
40 ident.as_name().into()
41 }
42
43 /// Calls `cb` with all paths, represented by this use item.
44 pub(crate) fn expand_use_item(
45 item_src: InFile<ast::UseItem>,
46 hygiene: &Hygiene,
47 mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<Name>),
48 ) {
49 if let Some(tree) = item_src.value.use_tree() {
50 lower::lower_use_tree(None, tree, hygiene, &mut cb);
51 }
52 }
53
54 pub fn is_ident(&self) -> bool {
55 self.kind == PathKind::Plain && self.segments.len() == 1
56 }
57
58 pub fn is_self(&self) -> bool {
59 self.kind == PathKind::Self_ && self.segments.is_empty()
60 }
61
62 /// If this path is a single identifier, like `foo`, return its name.
63 pub fn as_ident(&self) -> Option<&Name> {
64 if self.kind != PathKind::Plain || self.segments.len() > 1 {
65 return None;
66 }
67 self.segments.first()
68 }
23} 69}
24 70
25#[derive(Debug, Clone, PartialEq, Eq, Hash)] 71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub struct PathSegment { 72pub struct Path {
27 pub name: Name, 73 mod_path: ModPath,
28 pub args_and_bindings: Option<Arc<GenericArgs>>, 74 /// Invariant: the same len as self.path.segments
75 generic_args: Vec<Option<Arc<GenericArgs>>>,
29} 76}
30 77
31/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This 78/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
@@ -65,221 +112,110 @@ pub enum PathKind {
65} 112}
66 113
67impl Path { 114impl Path {
68 /// Calls `cb` with all paths, represented by this use item.
69 pub(crate) fn expand_use_item(
70 item_src: InFile<ast::UseItem>,
71 hygiene: &Hygiene,
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
73 ) {
74 if let Some(tree) = item_src.value.use_tree() {
75 lower_use::lower_use_tree(None, tree, hygiene, &mut cb);
76 }
77 }
78
79 pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path {
80 Path {
81 kind,
82 segments: segments
83 .into_iter()
84 .map(|name| PathSegment { name, args_and_bindings: None })
85 .collect(),
86 }
87 }
88
89 /// Converts an `ast::Path` to `Path`. Works with use trees. 115 /// Converts an `ast::Path` to `Path`. Works with use trees.
90 /// DEPRECATED: It does not handle `$crate` from macro call. 116 /// DEPRECATED: It does not handle `$crate` from macro call.
91 pub fn from_ast(path: ast::Path) -> Option<Path> { 117 pub fn from_ast(path: ast::Path) -> Option<Path> {
92 Path::from_src(path, &Hygiene::new_unhygienic()) 118 lower::lower_path(path, &Hygiene::new_unhygienic())
93 } 119 }
94 120
95 /// Converts an `ast::Path` to `Path`. Works with use trees. 121 /// Converts an `ast::Path` to `Path`. Works with use trees.
96 /// It correctly handles `$crate` based path from macro call. 122 /// It correctly handles `$crate` based path from macro call.
97 pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 123 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
98 let mut kind = PathKind::Plain; 124 lower::lower_path(path, hygiene)
99 let mut segments = Vec::new();
100 loop {
101 let segment = path.segment()?;
102
103 if segment.has_colon_colon() {
104 kind = PathKind::Abs;
105 }
106
107 match segment.kind()? {
108 ast::PathSegmentKind::Name(name_ref) => {
109 // FIXME: this should just return name
110 match hygiene.name_ref_to_name(name_ref) {
111 Either::Left(name) => {
112 let args = segment
113 .type_arg_list()
114 .and_then(GenericArgs::from_ast)
115 .or_else(|| {
116 GenericArgs::from_fn_like_path_ast(
117 segment.param_list(),
118 segment.ret_type(),
119 )
120 })
121 .map(Arc::new);
122 let segment = PathSegment { name, args_and_bindings: args };
123 segments.push(segment);
124 }
125 Either::Right(crate_id) => {
126 kind = PathKind::DollarCrate(crate_id);
127 break;
128 }
129 }
130 }
131 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
132 assert!(path.qualifier().is_none()); // this can only occur at the first segment
133
134 let self_type = TypeRef::from_ast(type_ref?);
135
136 match trait_ref {
137 // <T>::foo
138 None => {
139 kind = PathKind::Type(Box::new(self_type));
140 }
141 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
142 Some(trait_ref) => {
143 let path = Path::from_src(trait_ref.path()?, hygiene)?;
144 kind = path.kind;
145 let mut prefix_segments = path.segments;
146 prefix_segments.reverse();
147 segments.extend(prefix_segments);
148 // Insert the type reference (T in the above example) as Self parameter for the trait
149 let mut last_segment = segments.last_mut()?;
150 if last_segment.args_and_bindings.is_none() {
151 last_segment.args_and_bindings =
152 Some(Arc::new(GenericArgs::empty()));
153 };
154 let args = last_segment.args_and_bindings.as_mut().unwrap();
155 let mut args_inner = Arc::make_mut(args);
156 args_inner.has_self_type = true;
157 args_inner.args.insert(0, GenericArg::Type(self_type));
158 }
159 }
160 }
161 ast::PathSegmentKind::CrateKw => {
162 kind = PathKind::Crate;
163 break;
164 }
165 ast::PathSegmentKind::SelfKw => {
166 kind = PathKind::Self_;
167 break;
168 }
169 ast::PathSegmentKind::SuperKw => {
170 kind = PathKind::Super;
171 break;
172 }
173 }
174 path = match qualifier(&path) {
175 Some(it) => it,
176 None => break,
177 };
178 }
179 segments.reverse();
180 return Some(Path { kind, segments });
181
182 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
183 if let Some(q) = path.qualifier() {
184 return Some(q);
185 }
186 // FIXME: this bottom up traversal is not too precise.
187 // Should we handle do a top-down analysis, recording results?
188 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
189 let use_tree = use_tree_list.parent_use_tree();
190 use_tree.path()
191 }
192 } 125 }
193 126
194 /// Converts an `ast::NameRef` into a single-identifier `Path`. 127 /// Converts an `ast::NameRef` into a single-identifier `Path`.
195 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { 128 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
196 name_ref.as_name().into() 129 Path { mod_path: name_ref.as_name().into(), generic_args: vec![None] }
197 } 130 }
198 131
199 /// Converts an `tt::Ident` into a single-identifier `Path`. 132 /// `true` if this path is just a standalone `self`
200 pub(crate) fn from_tt_ident(ident: &tt::Ident) -> Path { 133 pub fn is_self(&self) -> bool {
201 ident.as_name().into() 134 self.mod_path.is_self()
202 } 135 }
203 136
204 /// `true` is this path is a single identifier, like `foo` 137 pub fn kind(&self) -> &PathKind {
205 pub fn is_ident(&self) -> bool { 138 &self.mod_path.kind
206 self.kind == PathKind::Plain && self.segments.len() == 1
207 } 139 }
208 140
209 /// `true` if this path is just a standalone `self` 141 pub fn segments(&self) -> PathSegments<'_> {
210 pub fn is_self(&self) -> bool { 142 PathSegments {
211 self.kind == PathKind::Self_ && self.segments.is_empty() 143 segments: self.mod_path.segments.as_slice(),
144 generic_args: self.generic_args.as_slice(),
145 }
212 } 146 }
213 147
214 /// If this path is a single identifier, like `foo`, return its name. 148 pub fn mod_path(&self) -> &ModPath {
215 pub fn as_ident(&self) -> Option<&Name> { 149 &self.mod_path
216 if self.kind != PathKind::Plain || self.segments.len() > 1 { 150 }
151
152 pub fn qualifier(&self) -> Option<Path> {
153 if self.mod_path.is_ident() {
217 return None; 154 return None;
218 } 155 }
219 self.segments.first().map(|s| &s.name) 156 let res = Path {
157 mod_path: ModPath {
158 kind: self.mod_path.kind.clone(),
159 segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
160 },
161 generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
162 };
163 Some(res)
220 } 164 }
165}
221 166
222 pub fn expand_macro_expr(&self) -> Option<Name> { 167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
223 self.as_ident().and_then(|name| Some(name.clone())) 168pub struct PathSegment<'a> {
224 } 169 pub name: &'a Name,
170 pub args_and_bindings: Option<&'a GenericArgs>,
171}
225 172
226 pub fn is_type_relative(&self) -> bool { 173pub struct PathSegments<'a> {
227 match self.kind { 174 segments: &'a [Name],
228 PathKind::Type(_) => true, 175 generic_args: &'a [Option<Arc<GenericArgs>>],
229 _ => false, 176}
230 } 177
178impl<'a> PathSegments<'a> {
179 pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] };
180 pub fn is_empty(&self) -> bool {
181 self.len() == 0
182 }
183 pub fn len(&self) -> usize {
184 self.segments.len()
185 }
186 pub fn first(&self) -> Option<PathSegment<'a>> {
187 self.get(0)
188 }
189 pub fn last(&self) -> Option<PathSegment<'a>> {
190 self.get(self.len().checked_sub(1)?)
191 }
192 pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
193 assert_eq!(self.segments.len(), self.generic_args.len());
194 let res = PathSegment {
195 name: self.segments.get(idx)?,
196 args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it),
197 };
198 Some(res)
199 }
200 pub fn skip(&self, len: usize) -> PathSegments<'a> {
201 assert_eq!(self.segments.len(), self.generic_args.len());
202 PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] }
203 }
204 pub fn take(&self, len: usize) -> PathSegments<'a> {
205 assert_eq!(self.segments.len(), self.generic_args.len());
206 PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] }
207 }
208 pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
209 self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment {
210 name,
211 args_and_bindings: args.as_ref().map(|it| &**it),
212 })
231 } 213 }
232} 214}
233 215
234impl GenericArgs { 216impl GenericArgs {
235 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { 217 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
236 let mut args = Vec::new(); 218 lower::lower_generic_args(node)
237 for type_arg in node.type_args() {
238 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
239 args.push(GenericArg::Type(type_ref));
240 }
241 // lifetimes ignored for now
242 let mut bindings = Vec::new();
243 for assoc_type_arg in node.assoc_type_args() {
244 if let Some(name_ref) = assoc_type_arg.name_ref() {
245 let name = name_ref.as_name();
246 let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref());
247 bindings.push((name, type_ref));
248 }
249 }
250 if args.is_empty() && bindings.is_empty() {
251 None
252 } else {
253 Some(GenericArgs { args, has_self_type: false, bindings })
254 }
255 }
256
257 /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
258 /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
259 pub(crate) fn from_fn_like_path_ast(
260 params: Option<ast::ParamList>,
261 ret_type: Option<ast::RetType>,
262 ) -> Option<GenericArgs> {
263 let mut args = Vec::new();
264 let mut bindings = Vec::new();
265 if let Some(params) = params {
266 let mut param_types = Vec::new();
267 for param in params.params() {
268 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
269 param_types.push(type_ref);
270 }
271 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
272 args.push(arg);
273 }
274 if let Some(ret_type) = ret_type {
275 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
276 bindings.push((name![Output], type_ref))
277 }
278 if args.is_empty() && bindings.is_empty() {
279 None
280 } else {
281 Some(GenericArgs { args, has_self_type: false, bindings })
282 }
283 } 219 }
284 220
285 pub(crate) fn empty() -> GenericArgs { 221 pub(crate) fn empty() -> GenericArgs {
@@ -289,7 +225,16 @@ impl GenericArgs {
289 225
290impl From<Name> for Path { 226impl From<Name> for Path {
291 fn from(name: Name) -> Path { 227 fn from(name: Name) -> Path {
292 Path::from_simple_segments(PathKind::Plain, iter::once(name)) 228 Path {
229 mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)),
230 generic_args: vec![None],
231 }
232 }
233}
234
235impl From<Name> for ModPath {
236 fn from(name: Name) -> ModPath {
237 ModPath::from_simple_segments(PathKind::Plain, iter::once(name))
293 } 238 }
294} 239}
295 240
@@ -319,7 +264,7 @@ macro_rules! __known_path {
319macro_rules! __path { 264macro_rules! __path {
320 ($start:ident $(:: $seg:ident)*) => ({ 265 ($start:ident $(:: $seg:ident)*) => ({
321 $crate::__known_path!($start $(:: $seg)*); 266 $crate::__known_path!($start $(:: $seg)*);
322 $crate::path::Path::from_simple_segments($crate::path::PathKind::Abs, vec![ 267 $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec![
323 $crate::path::__name![$start], $($crate::path::__name![$seg],)* 268 $crate::path::__name![$start], $($crate::path::__name![$seg],)*
324 ]) 269 ])
325 }); 270 });
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
new file mode 100644
index 000000000..a2e995198
--- /dev/null
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -0,0 +1,176 @@
1//! Transforms syntax into `Path` objects, ideally with accounting for hygiene
2
3mod lower_use;
4
5use std::sync::Arc;
6
7use either::Either;
8use hir_expand::{
9 hygiene::Hygiene,
10 name::{name, AsName},
11};
12use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner};
13
14use crate::{
15 path::{GenericArg, GenericArgs, ModPath, Path, PathKind},
16 type_ref::TypeRef,
17};
18
19pub(super) use lower_use::lower_use_tree;
20
21/// Converts an `ast::Path` to `Path`. Works with use trees.
22/// It correctly handles `$crate` based path from macro call.
23pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
24 let mut kind = PathKind::Plain;
25 let mut segments = Vec::new();
26 let mut generic_args = Vec::new();
27 loop {
28 let segment = path.segment()?;
29
30 if segment.has_colon_colon() {
31 kind = PathKind::Abs;
32 }
33
34 match segment.kind()? {
35 ast::PathSegmentKind::Name(name_ref) => {
36 // FIXME: this should just return name
37 match hygiene.name_ref_to_name(name_ref) {
38 Either::Left(name) => {
39 let args = segment
40 .type_arg_list()
41 .and_then(lower_generic_args)
42 .or_else(|| {
43 lower_generic_args_from_fn_path(
44 segment.param_list(),
45 segment.ret_type(),
46 )
47 })
48 .map(Arc::new);
49 segments.push(name);
50 generic_args.push(args)
51 }
52 Either::Right(crate_id) => {
53 kind = PathKind::DollarCrate(crate_id);
54 break;
55 }
56 }
57 }
58 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
59 assert!(path.qualifier().is_none()); // this can only occur at the first segment
60
61 let self_type = TypeRef::from_ast(type_ref?);
62
63 match trait_ref {
64 // <T>::foo
65 None => {
66 kind = PathKind::Type(Box::new(self_type));
67 }
68 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
69 Some(trait_ref) => {
70 let path = Path::from_src(trait_ref.path()?, hygiene)?;
71 kind = path.mod_path.kind;
72
73 let mut prefix_segments = path.mod_path.segments;
74 prefix_segments.reverse();
75 segments.extend(prefix_segments);
76
77 let mut prefix_args = path.generic_args;
78 prefix_args.reverse();
79 generic_args.extend(prefix_args);
80
81 // Insert the type reference (T in the above example) as Self parameter for the trait
82 let last_segment = generic_args.last_mut()?;
83 if last_segment.is_none() {
84 *last_segment = Some(Arc::new(GenericArgs::empty()));
85 };
86 let args = last_segment.as_mut().unwrap();
87 let mut args_inner = Arc::make_mut(args);
88 args_inner.has_self_type = true;
89 args_inner.args.insert(0, GenericArg::Type(self_type));
90 }
91 }
92 }
93 ast::PathSegmentKind::CrateKw => {
94 kind = PathKind::Crate;
95 break;
96 }
97 ast::PathSegmentKind::SelfKw => {
98 kind = PathKind::Self_;
99 break;
100 }
101 ast::PathSegmentKind::SuperKw => {
102 kind = PathKind::Super;
103 break;
104 }
105 }
106 path = match qualifier(&path) {
107 Some(it) => it,
108 None => break,
109 };
110 }
111 segments.reverse();
112 generic_args.reverse();
113 let mod_path = ModPath { kind, segments };
114 return Some(Path { mod_path, generic_args });
115
116 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
117 if let Some(q) = path.qualifier() {
118 return Some(q);
119 }
120 // FIXME: this bottom up traversal is not too precise.
121 // Should we handle do a top-down analysis, recording results?
122 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
123 let use_tree = use_tree_list.parent_use_tree();
124 use_tree.path()
125 }
126}
127
128pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> {
129 let mut args = Vec::new();
130 for type_arg in node.type_args() {
131 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
132 args.push(GenericArg::Type(type_ref));
133 }
134 // lifetimes ignored for now
135 let mut bindings = Vec::new();
136 for assoc_type_arg in node.assoc_type_args() {
137 if let Some(name_ref) = assoc_type_arg.name_ref() {
138 let name = name_ref.as_name();
139 let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref());
140 bindings.push((name, type_ref));
141 }
142 }
143 if args.is_empty() && bindings.is_empty() {
144 None
145 } else {
146 Some(GenericArgs { args, has_self_type: false, bindings })
147 }
148}
149
150/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
151/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
152fn lower_generic_args_from_fn_path(
153 params: Option<ast::ParamList>,
154 ret_type: Option<ast::RetType>,
155) -> Option<GenericArgs> {
156 let mut args = Vec::new();
157 let mut bindings = Vec::new();
158 if let Some(params) = params {
159 let mut param_types = Vec::new();
160 for param in params.params() {
161 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
162 param_types.push(type_ref);
163 }
164 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
165 args.push(arg);
166 }
167 if let Some(ret_type) = ret_type {
168 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
169 bindings.push((name![Output], type_ref))
170 }
171 if args.is_empty() && bindings.is_empty() {
172 None
173 } else {
174 Some(GenericArgs { args, has_self_type: false, bindings })
175 }
176}
diff --git a/crates/ra_hir_def/src/path/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
index e2e1f716d..ea3fdb56c 100644
--- a/crates/ra_hir_def/src/path/lower_use.rs
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -10,13 +10,13 @@ use hir_expand::{
10}; 10};
11use ra_syntax::ast::{self, NameOwner}; 11use ra_syntax::ast::{self, NameOwner};
12 12
13use crate::path::{Path, PathKind, PathSegment}; 13use crate::path::{ModPath, PathKind};
14 14
15pub(crate) fn lower_use_tree( 15pub(crate) fn lower_use_tree(
16 prefix: Option<Path>, 16 prefix: Option<ModPath>,
17 tree: ast::UseTree, 17 tree: ast::UseTree,
18 hygiene: &Hygiene, 18 hygiene: &Hygiene,
19 cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option<Name>), 19 cb: &mut dyn FnMut(ModPath, &ast::UseTree, bool, Option<Name>),
20) { 20) {
21 if let Some(use_tree_list) = tree.use_tree_list() { 21 if let Some(use_tree_list) = tree.use_tree_list() {
22 let prefix = match tree.path() { 22 let prefix = match tree.path() {
@@ -57,7 +57,7 @@ pub(crate) fn lower_use_tree(
57 } 57 }
58} 58}
59 59
60fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 60fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
61 let prefix = if let Some(qual) = path.qualifier() { 61 let prefix = if let Some(qual) = path.qualifier() {
62 Some(convert_path(prefix, qual, hygiene)?) 62 Some(convert_path(prefix, qual, hygiene)?)
63 } else { 63 } else {
@@ -70,18 +70,15 @@ fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Opt
70 match hygiene.name_ref_to_name(name_ref) { 70 match hygiene.name_ref_to_name(name_ref) {
71 Either::Left(name) => { 71 Either::Left(name) => {
72 // no type args in use 72 // no type args in use
73 let mut res = prefix.unwrap_or_else(|| Path { 73 let mut res = prefix.unwrap_or_else(|| ModPath {
74 kind: PathKind::Plain, 74 kind: PathKind::Plain,
75 segments: Vec::with_capacity(1), 75 segments: Vec::with_capacity(1),
76 }); 76 });
77 res.segments.push(PathSegment { 77 res.segments.push(name);
78 name,
79 args_and_bindings: None, // no type args in use
80 });
81 res 78 res
82 } 79 }
83 Either::Right(crate_id) => { 80 Either::Right(crate_id) => {
84 return Some(Path::from_simple_segments( 81 return Some(ModPath::from_simple_segments(
85 PathKind::DollarCrate(crate_id), 82 PathKind::DollarCrate(crate_id),
86 iter::empty(), 83 iter::empty(),
87 )) 84 ))
@@ -92,19 +89,19 @@ fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Opt
92 if prefix.is_some() { 89 if prefix.is_some() {
93 return None; 90 return None;
94 } 91 }
95 Path::from_simple_segments(PathKind::Crate, iter::empty()) 92 ModPath::from_simple_segments(PathKind::Crate, iter::empty())
96 } 93 }
97 ast::PathSegmentKind::SelfKw => { 94 ast::PathSegmentKind::SelfKw => {
98 if prefix.is_some() { 95 if prefix.is_some() {
99 return None; 96 return None;
100 } 97 }
101 Path::from_simple_segments(PathKind::Self_, iter::empty()) 98 ModPath::from_simple_segments(PathKind::Self_, iter::empty())
102 } 99 }
103 ast::PathSegmentKind::SuperKw => { 100 ast::PathSegmentKind::SuperKw => {
104 if prefix.is_some() { 101 if prefix.is_some() {
105 return None; 102 return None;
106 } 103 }
107 Path::from_simple_segments(PathKind::Super, iter::empty()) 104 ModPath::from_simple_segments(PathKind::Super, iter::empty())
108 } 105 }
109 ast::PathSegmentKind::Type { .. } => { 106 ast::PathSegmentKind::Type { .. } => {
110 // not allowed in imports 107 // not allowed in imports
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index b6d595a20..2694c0438 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -15,7 +15,7 @@ use crate::{
15 expr::{ExprId, PatId}, 15 expr::{ExprId, PatId},
16 generics::GenericParams, 16 generics::GenericParams,
17 nameres::{BuiltinShadowMode, CrateDefMap}, 17 nameres::{BuiltinShadowMode, CrateDefMap},
18 path::{Path, PathKind}, 18 path::{ModPath, PathKind},
19 per_ns::PerNs, 19 per_ns::PerNs,
20 AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, 20 AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId,
21 HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, 21 HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId,
@@ -91,7 +91,7 @@ pub enum ValueNs {
91 91
92impl Resolver { 92impl Resolver {
93 /// Resolve known trait from std, like `std::futures::Future` 93 /// Resolve known trait from std, like `std::futures::Future`
94 pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> { 94 pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &ModPath) -> Option<TraitId> {
95 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; 95 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
96 match res { 96 match res {
97 ModuleDefId::TraitId(it) => Some(it), 97 ModuleDefId::TraitId(it) => Some(it),
@@ -100,7 +100,7 @@ impl Resolver {
100 } 100 }
101 101
102 /// Resolve known struct from std, like `std::boxed::Box` 102 /// Resolve known struct from std, like `std::boxed::Box`
103 pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> { 103 pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &ModPath) -> Option<StructId> {
104 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; 104 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
105 match res { 105 match res {
106 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), 106 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
@@ -109,7 +109,7 @@ impl Resolver {
109 } 109 }
110 110
111 /// Resolve known enum from std, like `std::result::Result` 111 /// Resolve known enum from std, like `std::result::Result`
112 pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> { 112 pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &ModPath) -> Option<EnumId> {
113 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; 113 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
114 match res { 114 match res {
115 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), 115 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
@@ -120,33 +120,30 @@ impl Resolver {
120 fn resolve_module_path( 120 fn resolve_module_path(
121 &self, 121 &self,
122 db: &impl DefDatabase, 122 db: &impl DefDatabase,
123 path: &Path, 123 path: &ModPath,
124 shadow: BuiltinShadowMode, 124 shadow: BuiltinShadowMode,
125 ) -> PerNs { 125 ) -> PerNs {
126 let (item_map, module) = match self.module() { 126 let (item_map, module) = match self.module() {
127 Some(it) => it, 127 Some(it) => it,
128 None => return PerNs::none(), 128 None => return PerNs::none(),
129 }; 129 };
130 let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow); 130 let (module_res, segment_index) = item_map.resolve_path(db, module, &path, shadow);
131 if segment_index.is_some() { 131 if segment_index.is_some() {
132 return PerNs::none(); 132 return PerNs::none();
133 } 133 }
134 module_res 134 module_res
135 } 135 }
136 136
137 pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &Path) -> PerNs { 137 pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &ModPath) -> PerNs {
138 self.resolve_module_path(db, path, BuiltinShadowMode::Module) 138 self.resolve_module_path(db, path, BuiltinShadowMode::Module)
139 } 139 }
140 140
141 pub fn resolve_path_in_type_ns( 141 pub fn resolve_path_in_type_ns(
142 &self, 142 &self,
143 db: &impl DefDatabase, 143 db: &impl DefDatabase,
144 path: &Path, 144 path: &ModPath,
145 ) -> Option<(TypeNs, Option<usize>)> { 145 ) -> Option<(TypeNs, Option<usize>)> {
146 if path.is_type_relative() { 146 let first_name = path.segments.first()?;
147 return None;
148 }
149 let first_name = &path.segments.first()?.name;
150 let skip_to_mod = path.kind != PathKind::Plain; 147 let skip_to_mod = path.kind != PathKind::Plain;
151 for scope in self.scopes.iter().rev() { 148 for scope in self.scopes.iter().rev() {
152 match scope { 149 match scope {
@@ -178,7 +175,7 @@ impl Resolver {
178 let (module_def, idx) = m.crate_def_map.resolve_path( 175 let (module_def, idx) = m.crate_def_map.resolve_path(
179 db, 176 db,
180 m.module_id, 177 m.module_id,
181 path, 178 &path,
182 BuiltinShadowMode::Other, 179 BuiltinShadowMode::Other,
183 ); 180 );
184 let res = match module_def.take_types()? { 181 let res = match module_def.take_types()? {
@@ -205,7 +202,7 @@ impl Resolver {
205 pub fn resolve_path_in_type_ns_fully( 202 pub fn resolve_path_in_type_ns_fully(
206 &self, 203 &self,
207 db: &impl DefDatabase, 204 db: &impl DefDatabase,
208 path: &Path, 205 path: &ModPath,
209 ) -> Option<TypeNs> { 206 ) -> Option<TypeNs> {
210 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; 207 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?;
211 if unresolved.is_some() { 208 if unresolved.is_some() {
@@ -214,17 +211,14 @@ impl Resolver {
214 Some(res) 211 Some(res)
215 } 212 }
216 213
217 pub fn resolve_path_in_value_ns<'p>( 214 pub fn resolve_path_in_value_ns(
218 &self, 215 &self,
219 db: &impl DefDatabase, 216 db: &impl DefDatabase,
220 path: &'p Path, 217 path: &ModPath,
221 ) -> Option<ResolveValueResult> { 218 ) -> Option<ResolveValueResult> {
222 if path.is_type_relative() {
223 return None;
224 }
225 let n_segments = path.segments.len(); 219 let n_segments = path.segments.len();
226 let tmp = name![self]; 220 let tmp = name![self];
227 let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; 221 let first_name = if path.is_self() { &tmp } else { &path.segments.first()? };
228 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); 222 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
229 for scope in self.scopes.iter().rev() { 223 for scope in self.scopes.iter().rev() {
230 match scope { 224 match scope {
@@ -276,7 +270,7 @@ impl Resolver {
276 let (module_def, idx) = m.crate_def_map.resolve_path( 270 let (module_def, idx) = m.crate_def_map.resolve_path(
277 db, 271 db,
278 m.module_id, 272 m.module_id,
279 path, 273 &path,
280 BuiltinShadowMode::Other, 274 BuiltinShadowMode::Other,
281 ); 275 );
282 return match idx { 276 return match idx {
@@ -322,7 +316,7 @@ impl Resolver {
322 pub fn resolve_path_in_value_ns_fully( 316 pub fn resolve_path_in_value_ns_fully(
323 &self, 317 &self,
324 db: &impl DefDatabase, 318 db: &impl DefDatabase,
325 path: &Path, 319 path: &ModPath,
326 ) -> Option<ValueNs> { 320 ) -> Option<ValueNs> {
327 match self.resolve_path_in_value_ns(db, path)? { 321 match self.resolve_path_in_value_ns(db, path)? {
328 ResolveValueResult::ValueNs(it) => Some(it), 322 ResolveValueResult::ValueNs(it) => Some(it),
@@ -330,9 +324,13 @@ impl Resolver {
330 } 324 }
331 } 325 }
332 326
333 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 327 pub fn resolve_path_as_macro(
328 &self,
329 db: &impl DefDatabase,
330 path: &ModPath,
331 ) -> Option<MacroDefId> {
334 let (item_map, module) = self.module()?; 332 let (item_map, module) = self.module()?;
335 item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros() 333 item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros()
336 } 334 }
337 335
338 pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { 336 pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {