aboutsummaryrefslogtreecommitdiff
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
parent60bdb66ef23f78d8c73afa1897a4542e7e722ed2 (diff)
Lower `Fn(X, Y) -> Z` paths
-rw-r--r--crates/ra_hir/src/path.rs44
-rw-r--r--crates/ra_hir/src/ty/tests.rs16
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron2
4 files changed, 55 insertions, 13 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 }
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() {
3736trait FnOnce<Args> { 3736trait FnOnce<Args> {
3737 type Output; 3737 type Output;
3738 3738
3739 fn call_once(self, args: Args) -> Self::Output; 3739 fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
3740} 3740}
3741 3741
3742fn test<F: FnOnce(u32, u64) -> u128>(f: F) { 3742fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
@@ -3746,13 +3746,13 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
3746 @r###" 3746 @r###"
3747 [57; 61) 'self': Self 3747 [57; 61) 'self': Self
3748 [63; 67) 'args': Args 3748 [63; 67) 'args': Args
3749 [132; 133) 'f': F 3749 [150; 151) 'f': F
3750 [138; 166) '{ ...2)); }': () 3750 [156; 184) '{ ...2)); }': ()
3751 [144; 145) 'f': F 3751 [162; 163) 'f': F
3752 [144; 163) 'f.call...1, 2))': {unknown} 3752 [162; 181) 'f.call...1, 2))': {unknown}
3753 [156; 162) '(1, 2)': (i32, i32) 3753 [174; 180) '(1, 2)': (u32, u64)
3754 [157; 158) '1': i32 3754 [175; 176) '1': u32
3755 [160; 161) '2': i32 3755 [178; 179) '2': u64
3756 "### 3756 "###
3757 ); 3757 );
3758} 3758}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index bcf753f78..d274b6fbc 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -2312,6 +2312,12 @@ impl PathSegment {
2312 pub fn type_arg_list(&self) -> Option<TypeArgList> { 2312 pub fn type_arg_list(&self) -> Option<TypeArgList> {
2313 AstChildren::new(&self.syntax).next() 2313 AstChildren::new(&self.syntax).next()
2314 } 2314 }
2315 pub fn param_list(&self) -> Option<ParamList> {
2316 AstChildren::new(&self.syntax).next()
2317 }
2318 pub fn ret_type(&self) -> Option<RetType> {
2319 AstChildren::new(&self.syntax).next()
2320 }
2315} 2321}
2316#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2322#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2317pub struct PathType { 2323pub struct PathType {
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 3e6c2d3f3..993e58e64 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -684,7 +684,7 @@ Grammar(
684 ] 684 ]
685 ), 685 ),
686 "PathSegment": ( 686 "PathSegment": (
687 options: [ "NameRef", "TypeArgList" ] 687 options: [ "NameRef", "TypeArgList", "ParamList", "RetType" ]
688 ), 688 ),
689 "TypeArgList": (collections: [ 689 "TypeArgList": (collections: [
690 ("type_args", "TypeArg"), 690 ("type_args", "TypeArg"),