diff options
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r-- | crates/ra_hir/src/path.rs | 100 |
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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::{iter, sync::Arc}; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use 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)] |
46 | pub enum PathKind { | 46 | pub 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 | ||
55 | impl Path { | 57 | impl 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 | ||
231 | impl From<Name> for Path { | 251 | impl 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 | |||
342 | pub 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 | } | ||