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.rs38
1 files changed, 37 insertions, 1 deletions
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 882db7681..5ee71e421 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -25,6 +25,12 @@ pub struct PathSegment {
25#[derive(Debug, Clone, PartialEq, Eq, Hash)] 25#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub struct GenericArgs { 26pub struct GenericArgs {
27 pub args: Vec<GenericArg>, 27 pub args: Vec<GenericArg>,
28 /// This specifies whether the args contain a Self type as the first
29 /// element. This is the case for path segments like `<T as Trait>`, where
30 /// `T` is actually a type parameter for the path `Trait` specifying the
31 /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
32 /// is left out.
33 pub has_self_type: bool,
28 // someday also bindings 34 // someday also bindings
29} 35}
30 36
@@ -74,6 +80,28 @@ impl Path {
74 let segment = PathSegment { name: name.as_name(), args_and_bindings: args }; 80 let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
75 segments.push(segment); 81 segments.push(segment);
76 } 82 }
83 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
84 assert!(path.qualifier().is_none()); // this can only occur at the first segment
85
86 // FIXME: handle <T> syntax (type segments without trait)
87
88 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
89 let path = Path::from_ast(trait_ref?.path()?)?;
90 kind = path.kind;
91 let mut prefix_segments = path.segments;
92 prefix_segments.reverse();
93 segments.extend(prefix_segments);
94 // Insert the type reference (T in the above example) as Self parameter for the trait
95 let self_type = TypeRef::from_ast(type_ref?);
96 let mut last_segment = segments.last_mut()?;
97 if last_segment.args_and_bindings.is_none() {
98 last_segment.args_and_bindings = Some(Arc::new(GenericArgs::empty()));
99 };
100 let args = last_segment.args_and_bindings.as_mut().unwrap();
101 let mut args_inner = Arc::make_mut(args);
102 args_inner.has_self_type = true;
103 args_inner.args.insert(0, GenericArg::Type(self_type));
104 }
77 ast::PathSegmentKind::CrateKw => { 105 ast::PathSegmentKind::CrateKw => {
78 kind = PathKind::Crate; 106 kind = PathKind::Crate;
79 break; 107 break;
@@ -144,11 +172,15 @@ impl GenericArgs {
144 } 172 }
145 // lifetimes and assoc type args ignored for now 173 // lifetimes and assoc type args ignored for now
146 if !args.is_empty() { 174 if !args.is_empty() {
147 Some(GenericArgs { args }) 175 Some(GenericArgs { args, has_self_type: false })
148 } else { 176 } else {
149 None 177 None
150 } 178 }
151 } 179 }
180
181 pub(crate) fn empty() -> GenericArgs {
182 GenericArgs { args: Vec::new(), has_self_type: false }
183 }
152} 184}
153 185
154impl From<Name> for Path { 186impl From<Name> for Path {
@@ -236,6 +268,10 @@ fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
236 } 268 }
237 Path { kind: PathKind::Super, segments: Vec::new() } 269 Path { kind: PathKind::Super, segments: Vec::new() }
238 } 270 }
271 ast::PathSegmentKind::Type { .. } => {
272 // not allowed in imports
273 return None;
274 }
239 }; 275 };
240 Some(res) 276 Some(res)
241} 277}