diff options
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r-- | crates/ra_hir/src/path.rs | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index d6c78593b..7c19fda14 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}, |
@@ -10,6 +10,7 @@ use crate::{name, type_ref::TypeRef, AsName, Name}; | |||
10 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 10 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
11 | pub struct Path { | 11 | pub struct Path { |
12 | pub kind: PathKind, | 12 | pub kind: PathKind, |
13 | pub type_ref: Option<Box<TypeRef>>, | ||
13 | pub segments: Vec<PathSegment>, | 14 | pub segments: Vec<PathSegment>, |
14 | } | 15 | } |
15 | 16 | ||
@@ -50,6 +51,8 @@ pub enum PathKind { | |||
50 | Crate, | 51 | Crate, |
51 | // Absolute path | 52 | // Absolute path |
52 | Abs, | 53 | Abs, |
54 | // Type based path like `<T>::foo` | ||
55 | Type, | ||
53 | } | 56 | } |
54 | 57 | ||
55 | impl Path { | 58 | impl Path { |
@@ -63,10 +66,22 @@ impl Path { | |||
63 | } | 66 | } |
64 | } | 67 | } |
65 | 68 | ||
69 | pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path { | ||
70 | Path { | ||
71 | kind, | ||
72 | type_ref: None, | ||
73 | segments: segments | ||
74 | .into_iter() | ||
75 | .map(|name| PathSegment { name, args_and_bindings: None }) | ||
76 | .collect(), | ||
77 | } | ||
78 | } | ||
79 | |||
66 | /// Converts an `ast::Path` to `Path`. Works with use trees. | 80 | /// Converts an `ast::Path` to `Path`. Works with use trees. |
67 | pub fn from_ast(mut path: ast::Path) -> Option<Path> { | 81 | pub fn from_ast(mut path: ast::Path) -> Option<Path> { |
68 | let mut kind = PathKind::Plain; | 82 | let mut kind = PathKind::Plain; |
69 | let mut segments = Vec::new(); | 83 | let mut segments = Vec::new(); |
84 | let mut path_type_ref = None; | ||
70 | loop { | 85 | loop { |
71 | let segment = path.segment()?; | 86 | let segment = path.segment()?; |
72 | 87 | ||
@@ -92,24 +107,33 @@ impl Path { | |||
92 | ast::PathSegmentKind::Type { type_ref, trait_ref } => { | 107 | ast::PathSegmentKind::Type { type_ref, trait_ref } => { |
93 | assert!(path.qualifier().is_none()); // this can only occur at the first segment | 108 | assert!(path.qualifier().is_none()); // this can only occur at the first segment |
94 | 109 | ||
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?); | 110 | let self_type = TypeRef::from_ast(type_ref?); |
105 | let mut last_segment = segments.last_mut()?; | 111 | |
106 | if last_segment.args_and_bindings.is_none() { | 112 | match trait_ref { |
107 | last_segment.args_and_bindings = Some(Arc::new(GenericArgs::empty())); | 113 | // <T>::foo |
108 | }; | 114 | None => { |
109 | let args = last_segment.args_and_bindings.as_mut().unwrap(); | 115 | kind = PathKind::Type; |
110 | let mut args_inner = Arc::make_mut(args); | 116 | path_type_ref = Some(Box::new(self_type)); |
111 | args_inner.has_self_type = true; | 117 | } |
112 | args_inner.args.insert(0, GenericArg::Type(self_type)); | 118 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo |
119 | Some(trait_ref) => { | ||
120 | let path = Path::from_ast(trait_ref.path()?)?; | ||
121 | kind = path.kind; | ||
122 | let mut prefix_segments = path.segments; | ||
123 | prefix_segments.reverse(); | ||
124 | segments.extend(prefix_segments); | ||
125 | // Insert the type reference (T in the above example) as Self parameter for the trait | ||
126 | let mut last_segment = segments.last_mut()?; | ||
127 | if last_segment.args_and_bindings.is_none() { | ||
128 | last_segment.args_and_bindings = | ||
129 | Some(Arc::new(GenericArgs::empty())); | ||
130 | }; | ||
131 | let args = last_segment.args_and_bindings.as_mut().unwrap(); | ||
132 | let mut args_inner = Arc::make_mut(args); | ||
133 | args_inner.has_self_type = true; | ||
134 | args_inner.args.insert(0, GenericArg::Type(self_type)); | ||
135 | } | ||
136 | } | ||
113 | } | 137 | } |
114 | ast::PathSegmentKind::CrateKw => { | 138 | ast::PathSegmentKind::CrateKw => { |
115 | kind = PathKind::Crate; | 139 | kind = PathKind::Crate; |
@@ -130,7 +154,7 @@ impl Path { | |||
130 | }; | 154 | }; |
131 | } | 155 | } |
132 | segments.reverse(); | 156 | segments.reverse(); |
133 | return Some(Path { kind, segments }); | 157 | return Some(Path { kind, type_ref: path_type_ref, segments }); |
134 | 158 | ||
135 | fn qualifier(path: &ast::Path) -> Option<ast::Path> { | 159 | fn qualifier(path: &ast::Path) -> Option<ast::Path> { |
136 | if let Some(q) = path.qualifier() { | 160 | if let Some(q) = path.qualifier() { |
@@ -230,10 +254,7 @@ impl GenericArgs { | |||
230 | 254 | ||
231 | impl From<Name> for Path { | 255 | impl From<Name> for Path { |
232 | fn from(name: Name) -> Path { | 256 | fn from(name: Name) -> Path { |
233 | Path { | 257 | Path::from_simple_segments(PathKind::Plain, iter::once(name)) |
234 | kind: PathKind::Plain, | ||
235 | segments: vec![PathSegment { name, args_and_bindings: None }], | ||
236 | } | ||
237 | } | 258 | } |
238 | } | 259 | } |
239 | 260 | ||
@@ -287,8 +308,12 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> { | |||
287 | let segment = path.segment()?; | 308 | let segment = path.segment()?; |
288 | let res = match segment.kind()? { | 309 | let res = match segment.kind()? { |
289 | ast::PathSegmentKind::Name(name) => { | 310 | ast::PathSegmentKind::Name(name) => { |
290 | let mut res = prefix | 311 | // no type args in use |
291 | .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); | 312 | let mut res = prefix.unwrap_or_else(|| Path { |
313 | kind: PathKind::Plain, | ||
314 | type_ref: None, | ||
315 | segments: Vec::with_capacity(1), | ||
316 | }); | ||
292 | res.segments.push(PathSegment { | 317 | res.segments.push(PathSegment { |
293 | name: name.as_name(), | 318 | name: name.as_name(), |
294 | args_and_bindings: None, // no type args in use | 319 | args_and_bindings: None, // no type args in use |
@@ -299,19 +324,19 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> { | |||
299 | if prefix.is_some() { | 324 | if prefix.is_some() { |
300 | return None; | 325 | return None; |
301 | } | 326 | } |
302 | Path { kind: PathKind::Crate, segments: Vec::new() } | 327 | Path::from_simple_segments(PathKind::Crate, iter::empty()) |
303 | } | 328 | } |
304 | ast::PathSegmentKind::SelfKw => { | 329 | ast::PathSegmentKind::SelfKw => { |
305 | if prefix.is_some() { | 330 | if prefix.is_some() { |
306 | return None; | 331 | return None; |
307 | } | 332 | } |
308 | Path { kind: PathKind::Self_, segments: Vec::new() } | 333 | Path::from_simple_segments(PathKind::Self_, iter::empty()) |
309 | } | 334 | } |
310 | ast::PathSegmentKind::SuperKw => { | 335 | ast::PathSegmentKind::SuperKw => { |
311 | if prefix.is_some() { | 336 | if prefix.is_some() { |
312 | return None; | 337 | return None; |
313 | } | 338 | } |
314 | Path { kind: PathKind::Super, segments: Vec::new() } | 339 | Path::from_simple_segments(PathKind::Super, iter::empty()) |
315 | } | 340 | } |
316 | ast::PathSegmentKind::Type { .. } => { | 341 | ast::PathSegmentKind::Type { .. } => { |
317 | // not allowed in imports | 342 | // not allowed in imports |