aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/path.rs
diff options
context:
space:
mode:
authoruHOOCCOOHu <[email protected]>2019-09-11 19:01:07 +0100
committeruHOOCCOOHu <[email protected]>2019-09-15 12:40:32 +0100
commit4926bed42680d329f906be93450bec6b2ba0e99b (patch)
tree455c0bc9d839a18fffda6d018bf41d1c58ebfa52 /crates/ra_hir/src/path.rs
parent2d79a1ad83cc39075c7c9e3230973013c8c58b17 (diff)
Support path starting with a type
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r--crates/ra_hir/src/path.rs81
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 @@
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},
@@ -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)]
11pub struct Path { 11pub 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
55impl Path { 58impl 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
231impl From<Name> for Path { 255impl 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