From d21cdf3c998bb24e48e81a7e6909df2146ce097c Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 7 Sep 2019 15:13:05 +0200 Subject: Lower `Fn(X, Y) -> Z` paths --- crates/ra_hir/src/path.rs | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'crates/ra_hir/src/path.rs') 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 @@ use std::sync::Arc; use ra_syntax::{ - ast::{self, NameOwner}, + ast::{self, NameOwner, TypeAscriptionOwner}, AstNode, }; -use crate::{type_ref::TypeRef, AsName, Name}; +use crate::{name, type_ref::TypeRef, AsName, Name}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { @@ -76,8 +76,16 @@ impl Path { match segment.kind()? { ast::PathSegmentKind::Name(name) => { - let args = - segment.type_arg_list().and_then(GenericArgs::from_ast).map(Arc::new); + let args = segment + .type_arg_list() + .and_then(GenericArgs::from_ast) + .or_else(|| { + GenericArgs::from_fn_like_path_ast( + segment.param_list(), + segment.ret_type(), + ) + }) + .map(Arc::new); let segment = PathSegment { name: name.as_name(), args_and_bindings: args }; segments.push(segment); } @@ -187,6 +195,34 @@ impl GenericArgs { } } + /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) + /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). + pub(crate) fn from_fn_like_path_ast( + params: Option, + ret_type: Option, + ) -> Option { + let mut args = Vec::new(); + let mut bindings = Vec::new(); + if let Some(params) = params { + let mut param_types = Vec::new(); + for param in params.params() { + let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); + param_types.push(type_ref); + } + let arg = GenericArg::Type(TypeRef::Tuple(param_types)); + args.push(arg); + } + if let Some(ret_type) = ret_type { + let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); + bindings.push((name::OUTPUT, type_ref)) + } + if args.is_empty() && bindings.is_empty() { + None + } else { + Some(GenericArgs { args, has_self_type: false, bindings }) + } + } + pub(crate) fn empty() -> GenericArgs { GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() } } -- cgit v1.2.3