diff options
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r-- | crates/ra_hir/src/path.rs | 38 |
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)] |
26 | pub struct GenericArgs { | 26 | pub 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 | ||
154 | impl From<Name> for Path { | 186 | impl 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 | } |