aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assists/add_import.rs6
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/source_binder.rs56
-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
-rw-r--r--crates/ra_hir_ty/src/infer.rs2
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs25
-rw-r--r--crates/ra_hir_ty/src/lower.rs70
-rw-r--r--crates/ra_hir_ty/src/utils.rs5
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs7
18 files changed, 471 insertions, 354 deletions
diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs
index 363ade016..f81b4184a 100644
--- a/crates/ra_assists/src/assists/add_import.rs
+++ b/crates/ra_assists/src/assists/add_import.rs
@@ -578,7 +578,7 @@ fn apply_auto_import(
578 578
579fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> { 579fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
580 let mut ps = Vec::<SmolStr>::with_capacity(10); 580 let mut ps = Vec::<SmolStr>::with_capacity(10);
581 match path.kind { 581 match path.kind() {
582 hir::PathKind::Abs => ps.push("".into()), 582 hir::PathKind::Abs => ps.push("".into()),
583 hir::PathKind::Crate => ps.push("crate".into()), 583 hir::PathKind::Crate => ps.push("crate".into()),
584 hir::PathKind::Plain => {} 584 hir::PathKind::Plain => {}
@@ -586,9 +586,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
586 hir::PathKind::Super => ps.push("super".into()), 586 hir::PathKind::Super => ps.push("super".into()),
587 hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, 587 hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None,
588 } 588 }
589 for s in path.segments.iter() { 589 ps.extend(path.segments().iter().map(|it| it.name.to_string().into()));
590 ps.push(s.name.to_string().into());
591 }
592 Some(ps) 590 Some(ps)
593} 591}
594 592
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index e7602ee30..451b227a6 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -54,7 +54,7 @@ pub use hir_def::{
54 builtin_type::BuiltinType, 54 builtin_type::BuiltinType,
55 docs::Documentation, 55 docs::Documentation,
56 nameres::ModuleSource, 56 nameres::ModuleSource,
57 path::{Path, PathKind}, 57 path::{ModPath, Path, PathKind},
58 type_ref::Mutability, 58 type_ref::Mutability,
59}; 59};
60pub use hir_expand::{ 60pub use hir_expand::{
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index f82242c3a..d326169b3 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -258,7 +258,7 @@ impl SourceAnalyzer {
258 ) -> Option<MacroDef> { 258 ) -> Option<MacroDef> {
259 let hygiene = Hygiene::new(db, macro_call.file_id); 259 let hygiene = Hygiene::new(db, macro_call.file_id);
260 let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?; 260 let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?;
261 self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) 261 self.resolver.resolve_path_as_macro(db, path.mod_path()).map(|it| it.into())
262 } 262 }
263 263
264 pub fn resolve_hir_path( 264 pub fn resolve_hir_path(
@@ -266,40 +266,42 @@ impl SourceAnalyzer {
266 db: &impl HirDatabase, 266 db: &impl HirDatabase,
267 path: &crate::Path, 267 path: &crate::Path,
268 ) -> Option<PathResolution> { 268 ) -> Option<PathResolution> {
269 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { 269 let types =
270 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), 270 self.resolver.resolve_path_in_type_ns_fully(db, path.mod_path()).map(|ty| match ty {
271 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), 271 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
272 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { 272 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
273 PathResolution::Def(Adt::from(it).into()) 273 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
274 } 274 PathResolution::Def(Adt::from(it).into())
275 TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
276 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
277 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
278 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
279 });
280 let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| {
281 let res = match val {
282 ValueNs::LocalBinding(pat_id) => {
283 let var = Local { parent: self.body_owner?, pat_id };
284 PathResolution::Local(var)
285 } 275 }
286 ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), 276 TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
287 ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), 277 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
288 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), 278 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
289 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), 279 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
290 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), 280 });
291 }; 281 let values =
292 Some(res) 282 self.resolver.resolve_path_in_value_ns_fully(db, path.mod_path()).and_then(|val| {
293 }); 283 let res = match val {
284 ValueNs::LocalBinding(pat_id) => {
285 let var = Local { parent: self.body_owner?, pat_id };
286 PathResolution::Local(var)
287 }
288 ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()),
289 ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
290 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
291 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
292 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
293 };
294 Some(res)
295 });
294 296
295 let items = self 297 let items = self
296 .resolver 298 .resolver
297 .resolve_module_path_in_items(db, &path) 299 .resolve_module_path_in_items(db, path.mod_path())
298 .take_types() 300 .take_types()
299 .map(|it| PathResolution::Def(it.into())); 301 .map(|it| PathResolution::Def(it.into()));
300 types.or(values).or(items).or_else(|| { 302 types.or(values).or(items).or_else(|| {
301 self.resolver 303 self.resolver
302 .resolve_path_as_macro(db, &path) 304 .resolve_path_as_macro(db, path.mod_path())
303 .map(|def| PathResolution::Macro(def.into())) 305 .map(|def| PathResolution::Macro(def.into()))
304 }) 306 })
305 } 307 }
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)) {
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index f1b7e9442..af42854cc 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -386,7 +386,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
386 let resolver = &self.resolver; 386 let resolver = &self.resolver;
387 // FIXME: this should resolve assoc items as well, see this example: 387 // FIXME: this should resolve assoc items as well, see this example:
388 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 388 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
389 match resolver.resolve_path_in_type_ns_fully(self.db, &path) { 389 match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) {
390 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { 390 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
391 let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); 391 let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into());
392 let ty = self.db.ty(strukt.into()); 392 let ty = self.db.ty(strukt.into());
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 37db005ea..3bae0ca6c 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -32,21 +32,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
32 path: &Path, 32 path: &Path,
33 id: ExprOrPatId, 33 id: ExprOrPatId,
34 ) -> Option<Ty> { 34 ) -> Option<Ty> {
35 let (value, self_subst) = if let PathKind::Type(type_ref) = &path.kind { 35 let (value, self_subst) = if let PathKind::Type(type_ref) = path.kind() {
36 if path.segments.is_empty() { 36 if path.segments().is_empty() {
37 // This can't actually happen syntax-wise 37 // This can't actually happen syntax-wise
38 return None; 38 return None;
39 } 39 }
40 let ty = self.make_ty(type_ref); 40 let ty = self.make_ty(type_ref);
41 let remaining_segments_for_ty = &path.segments[..path.segments.len() - 1]; 41 let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1);
42 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); 42 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
43 self.resolve_ty_assoc_item( 43 self.resolve_ty_assoc_item(
44 ty, 44 ty,
45 &path.segments.last().expect("path had at least one segment").name, 45 &path.segments().last().expect("path had at least one segment").name,
46 id, 46 id,
47 )? 47 )?
48 } else { 48 } else {
49 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; 49 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, path.mod_path())?;
50 50
51 match value_or_partial { 51 match value_or_partial {
52 ResolveValueResult::ValueNs(it) => (it, None), 52 ResolveValueResult::ValueNs(it) => (it, None),
@@ -85,13 +85,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
85 remaining_index: usize, 85 remaining_index: usize,
86 id: ExprOrPatId, 86 id: ExprOrPatId,
87 ) -> Option<(ValueNs, Option<Substs>)> { 87 ) -> Option<(ValueNs, Option<Substs>)> {
88 assert!(remaining_index < path.segments.len()); 88 assert!(remaining_index < path.segments().len());
89 // there may be more intermediate segments between the resolved one and 89 // there may be more intermediate segments between the resolved one and
90 // the end. Only the last segment needs to be resolved to a value; from 90 // the end. Only the last segment needs to be resolved to a value; from
91 // the segments before that, we need to get either a type or a trait ref. 91 // the segments before that, we need to get either a type or a trait ref.
92 92
93 let resolved_segment = &path.segments[remaining_index - 1]; 93 let resolved_segment = path.segments().get(remaining_index - 1).unwrap();
94 let remaining_segments = &path.segments[remaining_index..]; 94 let remaining_segments = path.segments().skip(remaining_index);
95 let is_before_last = remaining_segments.len() == 1; 95 let is_before_last = remaining_segments.len() == 1;
96 96
97 match (def, is_before_last) { 97 match (def, is_before_last) {
@@ -112,7 +112,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
112 // trait but it's not the last segment, so the next segment 112 // trait but it's not the last segment, so the next segment
113 // should resolve to an associated type of that trait (e.g. `<T 113 // should resolve to an associated type of that trait (e.g. `<T
114 // as Iterator>::Item::default`) 114 // as Iterator>::Item::default`)
115 let remaining_segments_for_ty = &remaining_segments[..remaining_segments.len() - 1]; 115 let remaining_segments_for_ty =
116 remaining_segments.take(remaining_segments.len() - 1);
116 let ty = Ty::from_partly_resolved_hir_path( 117 let ty = Ty::from_partly_resolved_hir_path(
117 self.db, 118 self.db,
118 &self.resolver, 119 &self.resolver,
@@ -138,7 +139,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
138 fn resolve_trait_assoc_item( 139 fn resolve_trait_assoc_item(
139 &mut self, 140 &mut self,
140 trait_ref: TraitRef, 141 trait_ref: TraitRef,
141 segment: &PathSegment, 142 segment: PathSegment<'_>,
142 id: ExprOrPatId, 143 id: ExprOrPatId,
143 ) -> Option<(ValueNs, Option<Substs>)> { 144 ) -> Option<(ValueNs, Option<Substs>)> {
144 let trait_ = trait_ref.trait_; 145 let trait_ = trait_ref.trait_;
@@ -150,7 +151,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
150 .map(|(_name, id)| (*id).into()) 151 .map(|(_name, id)| (*id).into())
151 .find_map(|item| match item { 152 .find_map(|item| match item {
152 AssocItemId::FunctionId(func) => { 153 AssocItemId::FunctionId(func) => {
153 if segment.name == self.db.function_data(func).name { 154 if segment.name == &self.db.function_data(func).name {
154 Some(AssocItemId::FunctionId(func)) 155 Some(AssocItemId::FunctionId(func))
155 } else { 156 } else {
156 None 157 None
@@ -158,7 +159,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
158 } 159 }
159 160
160 AssocItemId::ConstId(konst) => { 161 AssocItemId::ConstId(konst) => {
161 if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == &segment.name) 162 if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == segment.name)
162 { 163 {
163 Some(AssocItemId::ConstId(konst)) 164 Some(AssocItemId::ConstId(konst))
164 } else { 165 } else {
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 5f795bc02..a4ddfc8ef 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -11,7 +11,7 @@ use std::sync::Arc;
11use hir_def::{ 11use hir_def::{
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 generics::WherePredicate, 13 generics::WherePredicate,
14 path::{GenericArg, Path, PathKind, PathSegment}, 14 path::{GenericArg, Path, PathKind, PathSegment, PathSegments},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, 17 AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
@@ -101,13 +101,13 @@ impl Ty {
101 TypeRef::Path(path) => path, 101 TypeRef::Path(path) => path,
102 _ => return None, 102 _ => return None,
103 }; 103 };
104 if let PathKind::Type(_) = &path.kind { 104 if let PathKind::Type(_) = path.kind() {
105 return None; 105 return None;
106 } 106 }
107 if path.segments.len() > 1 { 107 if path.segments().len() > 1 {
108 return None; 108 return None;
109 } 109 }
110 let resolution = match resolver.resolve_path_in_type_ns(db, path) { 110 let resolution = match resolver.resolve_path_in_type_ns(db, path.mod_path()) {
111 Some((it, None)) => it, 111 Some((it, None)) => it,
112 _ => return None, 112 _ => return None,
113 }; 113 };
@@ -124,11 +124,11 @@ impl Ty {
124 db: &impl HirDatabase, 124 db: &impl HirDatabase,
125 resolver: &Resolver, 125 resolver: &Resolver,
126 ty: Ty, 126 ty: Ty,
127 remaining_segments: &[PathSegment], 127 remaining_segments: PathSegments<'_>,
128 ) -> Ty { 128 ) -> Ty {
129 if remaining_segments.len() == 1 { 129 if remaining_segments.len() == 1 {
130 // resolve unselected assoc types 130 // resolve unselected assoc types
131 let segment = &remaining_segments[0]; 131 let segment = remaining_segments.first().unwrap();
132 Ty::select_associated_type(db, resolver, ty, segment) 132 Ty::select_associated_type(db, resolver, ty, segment)
133 } else if remaining_segments.len() > 1 { 133 } else if remaining_segments.len() > 1 {
134 // FIXME report error (ambiguous associated type) 134 // FIXME report error (ambiguous associated type)
@@ -142,15 +142,15 @@ impl Ty {
142 db: &impl HirDatabase, 142 db: &impl HirDatabase,
143 resolver: &Resolver, 143 resolver: &Resolver,
144 resolution: TypeNs, 144 resolution: TypeNs,
145 resolved_segment: &PathSegment, 145 resolved_segment: PathSegment<'_>,
146 remaining_segments: &[PathSegment], 146 remaining_segments: PathSegments<'_>,
147 ) -> Ty { 147 ) -> Ty {
148 let ty = match resolution { 148 let ty = match resolution {
149 TypeNs::TraitId(trait_) => { 149 TypeNs::TraitId(trait_) => {
150 let trait_ref = 150 let trait_ref =
151 TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); 151 TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None);
152 return if remaining_segments.len() == 1 { 152 return if remaining_segments.len() == 1 {
153 let segment = &remaining_segments[0]; 153 let segment = remaining_segments.first().unwrap();
154 let associated_ty = associated_type_by_name_including_super_traits( 154 let associated_ty = associated_type_by_name_including_super_traits(
155 db, 155 db,
156 trait_ref.trait_, 156 trait_ref.trait_,
@@ -202,21 +202,21 @@ impl Ty {
202 202
203 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 203 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
204 // Resolve the path (in type namespace) 204 // Resolve the path (in type namespace)
205 if let PathKind::Type(type_ref) = &path.kind { 205 if let PathKind::Type(type_ref) = path.kind() {
206 let ty = Ty::from_hir(db, resolver, &type_ref); 206 let ty = Ty::from_hir(db, resolver, &type_ref);
207 let remaining_segments = &path.segments[..]; 207 return Ty::from_type_relative_path(db, resolver, ty, path.segments());
208 return Ty::from_type_relative_path(db, resolver, ty, remaining_segments);
209 } 208 }
210 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { 209 let (resolution, remaining_index) =
211 Some(it) => it, 210 match resolver.resolve_path_in_type_ns(db, path.mod_path()) {
212 None => return Ty::Unknown, 211 Some(it) => it,
213 }; 212 None => return Ty::Unknown,
213 };
214 let (resolved_segment, remaining_segments) = match remaining_index { 214 let (resolved_segment, remaining_segments) = match remaining_index {
215 None => ( 215 None => (
216 path.segments.last().expect("resolved path has at least one element"), 216 path.segments().last().expect("resolved path has at least one element"),
217 &[] as &[PathSegment], 217 PathSegments::EMPTY,
218 ), 218 ),
219 Some(i) => (&path.segments[i - 1], &path.segments[i..]), 219 Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)),
220 }; 220 };
221 Ty::from_partly_resolved_hir_path( 221 Ty::from_partly_resolved_hir_path(
222 db, 222 db,
@@ -231,7 +231,7 @@ impl Ty {
231 db: &impl HirDatabase, 231 db: &impl HirDatabase,
232 resolver: &Resolver, 232 resolver: &Resolver,
233 self_ty: Ty, 233 self_ty: Ty,
234 segment: &PathSegment, 234 segment: PathSegment<'_>,
235 ) -> Ty { 235 ) -> Ty {
236 let param_idx = match self_ty { 236 let param_idx = match self_ty {
237 Ty::Param { idx, .. } => idx, 237 Ty::Param { idx, .. } => idx,
@@ -261,7 +261,7 @@ impl Ty {
261 fn from_hir_path_inner( 261 fn from_hir_path_inner(
262 db: &impl HirDatabase, 262 db: &impl HirDatabase,
263 resolver: &Resolver, 263 resolver: &Resolver,
264 segment: &PathSegment, 264 segment: PathSegment<'_>,
265 typable: TyDefId, 265 typable: TyDefId,
266 ) -> Ty { 266 ) -> Ty {
267 let generic_def = match typable { 267 let generic_def = match typable {
@@ -284,7 +284,7 @@ impl Ty {
284 // special-case enum variants 284 // special-case enum variants
285 resolved: ValueTyDefId, 285 resolved: ValueTyDefId,
286 ) -> Substs { 286 ) -> Substs {
287 let last = path.segments.last().expect("path should have at least one segment"); 287 let last = path.segments().last().expect("path should have at least one segment");
288 let (segment, generic_def) = match resolved { 288 let (segment, generic_def) = match resolved {
289 ValueTyDefId::FunctionId(it) => (last, Some(it.into())), 289 ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
290 ValueTyDefId::StructId(it) => (last, Some(it.into())), 290 ValueTyDefId::StructId(it) => (last, Some(it.into())),
@@ -296,13 +296,11 @@ impl Ty {
296 // referring to the variant. So `Option::<T>::None` and 296 // referring to the variant. So `Option::<T>::None` and
297 // `Option::None::<T>` are both allowed (though the former is 297 // `Option::None::<T>` are both allowed (though the former is
298 // preferred). See also `def_ids_for_path_segments` in rustc. 298 // preferred). See also `def_ids_for_path_segments` in rustc.
299 let len = path.segments.len(); 299 let len = path.segments().len();
300 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { 300 let penultimate = if len >= 2 { path.segments().get(len - 2) } else { None };
301 // Option::<T>::None 301 let segment = match penultimate {
302 &path.segments[len - 2] 302 Some(segment) if segment.args_and_bindings.is_some() => segment,
303 } else { 303 _ => last,
304 // Option::None::<T>
305 last
306 }; 304 };
307 (segment, Some(var.parent.into())) 305 (segment, Some(var.parent.into()))
308 } 306 }
@@ -314,7 +312,7 @@ impl Ty {
314pub(super) fn substs_from_path_segment( 312pub(super) fn substs_from_path_segment(
315 db: &impl HirDatabase, 313 db: &impl HirDatabase,
316 resolver: &Resolver, 314 resolver: &Resolver,
317 segment: &PathSegment, 315 segment: PathSegment<'_>,
318 def_generic: Option<GenericDefId>, 316 def_generic: Option<GenericDefId>,
319 add_self_param: bool, 317 add_self_param: bool,
320) -> Substs { 318) -> Substs {
@@ -372,11 +370,11 @@ impl TraitRef {
372 path: &Path, 370 path: &Path,
373 explicit_self_ty: Option<Ty>, 371 explicit_self_ty: Option<Ty>,
374 ) -> Option<Self> { 372 ) -> Option<Self> {
375 let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? { 373 let resolved = match resolver.resolve_path_in_type_ns_fully(db, path.mod_path())? {
376 TypeNs::TraitId(tr) => tr, 374 TypeNs::TraitId(tr) => tr,
377 _ => return None, 375 _ => return None,
378 }; 376 };
379 let segment = path.segments.last().expect("path should have at least one segment"); 377 let segment = path.segments().last().expect("path should have at least one segment");
380 Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) 378 Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty))
381 } 379 }
382 380
@@ -384,7 +382,7 @@ impl TraitRef {
384 db: &impl HirDatabase, 382 db: &impl HirDatabase,
385 resolver: &Resolver, 383 resolver: &Resolver,
386 resolved: TraitId, 384 resolved: TraitId,
387 segment: &PathSegment, 385 segment: PathSegment<'_>,
388 explicit_self_ty: Option<Ty>, 386 explicit_self_ty: Option<Ty>,
389 ) -> Self { 387 ) -> Self {
390 let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); 388 let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved);
@@ -410,7 +408,7 @@ impl TraitRef {
410 fn substs_from_path( 408 fn substs_from_path(
411 db: &impl HirDatabase, 409 db: &impl HirDatabase,
412 resolver: &Resolver, 410 resolver: &Resolver,
413 segment: &PathSegment, 411 segment: PathSegment<'_>,
414 resolved: TraitId, 412 resolved: TraitId,
415 ) -> Substs { 413 ) -> Substs {
416 let has_self_param = 414 let has_self_param =
@@ -464,12 +462,12 @@ fn assoc_type_bindings_from_type_bound<'a>(
464 trait_ref: TraitRef, 462 trait_ref: TraitRef,
465) -> impl Iterator<Item = GenericPredicate> + 'a { 463) -> impl Iterator<Item = GenericPredicate> + 'a {
466 let last_segment = match bound { 464 let last_segment = match bound {
467 TypeBound::Path(path) => path.segments.last(), 465 TypeBound::Path(path) => path.segments().last(),
468 TypeBound::Error => None, 466 TypeBound::Error => None,
469 }; 467 };
470 last_segment 468 last_segment
471 .into_iter() 469 .into_iter()
472 .flat_map(|segment| segment.args_and_bindings.iter()) 470 .flat_map(|segment| segment.args_and_bindings.into_iter())
473 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 471 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
474 .map(move |(name, type_ref)| { 472 .map(move |(name, type_ref)| {
475 let associated_ty = 473 let associated_ty =
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index 0049d3c6f..29799a8cb 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -6,6 +6,7 @@ use hir_def::{
6 adt::VariantData, 6 adt::VariantData,
7 db::DefDatabase, 7 db::DefDatabase,
8 generics::{GenericParams, TypeParamData}, 8 generics::{GenericParams, TypeParamData},
9 path::Path,
9 resolver::{HasResolver, TypeNs}, 10 resolver::{HasResolver, TypeNs},
10 type_ref::TypeRef, 11 type_ref::TypeRef,
11 ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, 12 ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId,
@@ -22,10 +23,10 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
22 .where_predicates 23 .where_predicates
23 .iter() 24 .iter()
24 .filter_map(|pred| match &pred.type_ref { 25 .filter_map(|pred| match &pred.type_ref {
25 TypeRef::Path(p) if p.as_ident() == Some(&name![Self]) => pred.bound.as_path(), 26 TypeRef::Path(p) if p == &Path::from(name![Self]) => pred.bound.as_path(),
26 _ => None, 27 _ => None,
27 }) 28 })
28 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { 29 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
29 Some(TypeNs::TraitId(t)) => Some(t), 30 Some(TypeNs::TraitId(t)) => Some(t),
30 _ => None, 31 _ => None,
31 }) 32 })
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index ca0a483d4..981da2b79 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -188,10 +188,9 @@ impl<'a> CompletionContext<'a> {
188 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); 188 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
189 self.has_type_args = segment.type_arg_list().is_some(); 189 self.has_type_args = segment.type_arg_list().is_some();
190 190
191 if let Some(mut path) = hir::Path::from_ast(path.clone()) { 191 if let Some(path) = hir::Path::from_ast(path.clone()) {
192 if !path.is_ident() { 192 if let Some(path_prefix) = path.qualifier() {
193 path.segments.pop().unwrap(); 193 self.path_prefix = Some(path_prefix);
194 self.path_prefix = Some(path);
195 return; 194 return;
196 } 195 }
197 } 196 }