aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r--crates/ra_hir/src/path.rs100
1 files changed, 73 insertions, 27 deletions
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index d6c78593b..a61161b63 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -1,4 +1,4 @@
1use std::sync::Arc; 1use std::{iter, sync::Arc};
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, NameOwner, TypeAscriptionOwner}, 4 ast::{self, NameOwner, TypeAscriptionOwner},
@@ -42,7 +42,7 @@ pub enum GenericArg {
42 // or lifetime... 42 // or lifetime...
43} 43}
44 44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub enum PathKind { 46pub enum PathKind {
47 Plain, 47 Plain,
48 Self_, 48 Self_,
@@ -50,6 +50,8 @@ pub enum PathKind {
50 Crate, 50 Crate,
51 // Absolute path 51 // Absolute path
52 Abs, 52 Abs,
53 // Type based path like `<T>::foo`
54 Type(Box<TypeRef>),
53} 55}
54 56
55impl Path { 57impl Path {
@@ -63,6 +65,16 @@ impl Path {
63 } 65 }
64 } 66 }
65 67
68 pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path {
69 Path {
70 kind,
71 segments: segments
72 .into_iter()
73 .map(|name| PathSegment { name, args_and_bindings: None })
74 .collect(),
75 }
76 }
77
66 /// Converts an `ast::Path` to `Path`. Works with use trees. 78 /// Converts an `ast::Path` to `Path`. Works with use trees.
67 pub fn from_ast(mut path: ast::Path) -> Option<Path> { 79 pub fn from_ast(mut path: ast::Path) -> Option<Path> {
68 let mut kind = PathKind::Plain; 80 let mut kind = PathKind::Plain;
@@ -92,24 +104,32 @@ impl Path {
92 ast::PathSegmentKind::Type { type_ref, trait_ref } => { 104 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
93 assert!(path.qualifier().is_none()); // this can only occur at the first segment 105 assert!(path.qualifier().is_none()); // this can only occur at the first segment
94 106
95 // FIXME: handle <T> syntax (type segments without trait)
96
97 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
98 let path = Path::from_ast(trait_ref?.path()?)?;
99 kind = path.kind;
100 let mut prefix_segments = path.segments;
101 prefix_segments.reverse();
102 segments.extend(prefix_segments);
103 // Insert the type reference (T in the above example) as Self parameter for the trait
104 let self_type = TypeRef::from_ast(type_ref?); 107 let self_type = TypeRef::from_ast(type_ref?);
105 let mut last_segment = segments.last_mut()?; 108
106 if last_segment.args_and_bindings.is_none() { 109 match trait_ref {
107 last_segment.args_and_bindings = Some(Arc::new(GenericArgs::empty())); 110 // <T>::foo
108 }; 111 None => {
109 let args = last_segment.args_and_bindings.as_mut().unwrap(); 112 kind = PathKind::Type(Box::new(self_type));
110 let mut args_inner = Arc::make_mut(args); 113 }
111 args_inner.has_self_type = true; 114 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
112 args_inner.args.insert(0, GenericArg::Type(self_type)); 115 Some(trait_ref) => {
116 let path = Path::from_ast(trait_ref.path()?)?;
117 kind = path.kind;
118 let mut prefix_segments = path.segments;
119 prefix_segments.reverse();
120 segments.extend(prefix_segments);
121 // Insert the type reference (T in the above example) as Self parameter for the trait
122 let mut last_segment = segments.last_mut()?;
123 if last_segment.args_and_bindings.is_none() {
124 last_segment.args_and_bindings =
125 Some(Arc::new(GenericArgs::empty()));
126 };
127 let args = last_segment.args_and_bindings.as_mut().unwrap();
128 let mut args_inner = Arc::make_mut(args);
129 args_inner.has_self_type = true;
130 args_inner.args.insert(0, GenericArg::Type(self_type));
131 }
132 }
113 } 133 }
114 ast::PathSegmentKind::CrateKw => { 134 ast::PathSegmentKind::CrateKw => {
115 kind = PathKind::Crate; 135 kind = PathKind::Crate;
@@ -214,7 +234,7 @@ impl GenericArgs {
214 } 234 }
215 if let Some(ret_type) = ret_type { 235 if let Some(ret_type) = ret_type {
216 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); 236 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
217 bindings.push((name::OUTPUT, type_ref)) 237 bindings.push((name::OUTPUT_TYPE, type_ref))
218 } 238 }
219 if args.is_empty() && bindings.is_empty() { 239 if args.is_empty() && bindings.is_empty() {
220 None 240 None
@@ -230,10 +250,7 @@ impl GenericArgs {
230 250
231impl From<Name> for Path { 251impl From<Name> for Path {
232 fn from(name: Name) -> Path { 252 fn from(name: Name) -> Path {
233 Path { 253 Path::from_simple_segments(PathKind::Plain, iter::once(name))
234 kind: PathKind::Plain,
235 segments: vec![PathSegment { name, args_and_bindings: None }],
236 }
237 } 254 }
238} 255}
239 256
@@ -287,6 +304,7 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
287 let segment = path.segment()?; 304 let segment = path.segment()?;
288 let res = match segment.kind()? { 305 let res = match segment.kind()? {
289 ast::PathSegmentKind::Name(name) => { 306 ast::PathSegmentKind::Name(name) => {
307 // no type args in use
290 let mut res = prefix 308 let mut res = prefix
291 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); 309 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
292 res.segments.push(PathSegment { 310 res.segments.push(PathSegment {
@@ -299,19 +317,19 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
299 if prefix.is_some() { 317 if prefix.is_some() {
300 return None; 318 return None;
301 } 319 }
302 Path { kind: PathKind::Crate, segments: Vec::new() } 320 Path::from_simple_segments(PathKind::Crate, iter::empty())
303 } 321 }
304 ast::PathSegmentKind::SelfKw => { 322 ast::PathSegmentKind::SelfKw => {
305 if prefix.is_some() { 323 if prefix.is_some() {
306 return None; 324 return None;
307 } 325 }
308 Path { kind: PathKind::Self_, segments: Vec::new() } 326 Path::from_simple_segments(PathKind::Self_, iter::empty())
309 } 327 }
310 ast::PathSegmentKind::SuperKw => { 328 ast::PathSegmentKind::SuperKw => {
311 if prefix.is_some() { 329 if prefix.is_some() {
312 return None; 330 return None;
313 } 331 }
314 Path { kind: PathKind::Super, segments: Vec::new() } 332 Path::from_simple_segments(PathKind::Super, iter::empty())
315 } 333 }
316 ast::PathSegmentKind::Type { .. } => { 334 ast::PathSegmentKind::Type { .. } => {
317 // not allowed in imports 335 // not allowed in imports
@@ -320,3 +338,31 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
320 }; 338 };
321 Some(res) 339 Some(res)
322} 340}
341
342pub mod known {
343 use super::{Path, PathKind};
344 use crate::name;
345
346 pub fn std_iter_into_iterator() -> Path {
347 Path::from_simple_segments(
348 PathKind::Abs,
349 vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
350 )
351 }
352
353 pub fn std_ops_try() -> Path {
354 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
355 }
356
357 pub fn std_result_result() -> Path {
358 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
359 }
360
361 pub fn std_future_future() -> Path {
362 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
363 }
364
365 pub fn std_boxed_box() -> Path {
366 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
367 }
368}