aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/path.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-09-07 14:13:05 +0100
committerFlorian Diebold <[email protected]>2019-09-07 14:13:05 +0100
commitd21cdf3c998bb24e48e81a7e6909df2146ce097c (patch)
tree5f6928f1ee40b3f314c6f74f3552e06f820b5ca7 /crates/ra_hir/src/path.rs
parent60bdb66ef23f78d8c73afa1897a4542e7e722ed2 (diff)
Lower `Fn(X, Y) -> Z` paths
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r--crates/ra_hir/src/path.rs44
1 files changed, 40 insertions, 4 deletions
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 24316fc91..d6c78593b 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -1,11 +1,11 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, NameOwner}, 4 ast::{self, NameOwner, TypeAscriptionOwner},
5 AstNode, 5 AstNode,
6}; 6};
7 7
8use crate::{type_ref::TypeRef, AsName, Name}; 8use crate::{name, type_ref::TypeRef, AsName, Name};
9 9
10#[derive(Debug, Clone, PartialEq, Eq, Hash)] 10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct Path { 11pub struct Path {
@@ -76,8 +76,16 @@ impl Path {
76 76
77 match segment.kind()? { 77 match segment.kind()? {
78 ast::PathSegmentKind::Name(name) => { 78 ast::PathSegmentKind::Name(name) => {
79 let args = 79 let args = segment
80 segment.type_arg_list().and_then(GenericArgs::from_ast).map(Arc::new); 80 .type_arg_list()
81 .and_then(GenericArgs::from_ast)
82 .or_else(|| {
83 GenericArgs::from_fn_like_path_ast(
84 segment.param_list(),
85 segment.ret_type(),
86 )
87 })
88 .map(Arc::new);
81 let segment = PathSegment { name: name.as_name(), args_and_bindings: args }; 89 let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
82 segments.push(segment); 90 segments.push(segment);
83 } 91 }
@@ -187,6 +195,34 @@ impl GenericArgs {
187 } 195 }
188 } 196 }
189 197
198 /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
199 /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
200 pub(crate) fn from_fn_like_path_ast(
201 params: Option<ast::ParamList>,
202 ret_type: Option<ast::RetType>,
203 ) -> Option<GenericArgs> {
204 let mut args = Vec::new();
205 let mut bindings = Vec::new();
206 if let Some(params) = params {
207 let mut param_types = Vec::new();
208 for param in params.params() {
209 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
210 param_types.push(type_ref);
211 }
212 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
213 args.push(arg);
214 }
215 if let Some(ret_type) = ret_type {
216 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
217 bindings.push((name::OUTPUT, type_ref))
218 }
219 if args.is_empty() && bindings.is_empty() {
220 None
221 } else {
222 Some(GenericArgs { args, has_self_type: false, bindings })
223 }
224 }
225
190 pub(crate) fn empty() -> GenericArgs { 226 pub(crate) fn empty() -> GenericArgs {
191 GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() } 227 GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
192 } 228 }