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 +++++++++++++++++++++++++++++++++++++++---- crates/ra_hir/src/ty/tests.rs | 16 ++++++++-------- 2 files changed, 48 insertions(+), 12 deletions(-) (limited to 'crates/ra_hir/src') 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() } } diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 17c4e3556..c414e6a95 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -3736,7 +3736,7 @@ fn fn_trait() { trait FnOnce { type Output; - fn call_once(self, args: Args) -> Self::Output; + fn call_once(self, args: Args) -> >::Output; } fn test u128>(f: F) { @@ -3746,13 +3746,13 @@ fn test u128>(f: F) { @r###" [57; 61) 'self': Self [63; 67) 'args': Args - [132; 133) 'f': F - [138; 166) '{ ...2)); }': () - [144; 145) 'f': F - [144; 163) 'f.call...1, 2))': {unknown} - [156; 162) '(1, 2)': (i32, i32) - [157; 158) '1': i32 - [160; 161) '2': i32 + [150; 151) 'f': F + [156; 184) '{ ...2)); }': () + [162; 163) 'f': F + [162; 181) 'f.call...1, 2))': {unknown} + [174; 180) '(1, 2)': (u32, u64) + [175; 176) '1': u32 + [178; 179) '2': u64 "### ); } -- cgit v1.2.3