Lower Fn(X, Y) -> Z paths

This commit is contained in:
Florian Diebold 2019-09-07 15:13:05 +02:00
parent 60bdb66ef2
commit d21cdf3c99
4 changed files with 55 additions and 13 deletions

View File

@ -1,11 +1,11 @@
use std::sync::Arc; use std::sync::Arc;
use ra_syntax::{ use ra_syntax::{
ast::{self, NameOwner}, ast::{self, NameOwner, TypeAscriptionOwner},
AstNode, AstNode,
}; };
use crate::{type_ref::TypeRef, AsName, Name}; use crate::{name, type_ref::TypeRef, AsName, Name};
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path { pub struct Path {
@ -76,8 +76,16 @@ impl Path {
match segment.kind()? { match segment.kind()? {
ast::PathSegmentKind::Name(name) => { ast::PathSegmentKind::Name(name) => {
let args = let args = segment
segment.type_arg_list().and_then(GenericArgs::from_ast).map(Arc::new); .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 }; let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
segments.push(segment); 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<ast::ParamList>,
ret_type: Option<ast::RetType>,
) -> Option<GenericArgs> {
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 { pub(crate) fn empty() -> GenericArgs {
GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() } GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
} }

View File

@ -3736,7 +3736,7 @@ fn fn_trait() {
trait FnOnce<Args> { trait FnOnce<Args> {
type Output; type Output;
fn call_once(self, args: Args) -> Self::Output; fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
} }
fn test<F: FnOnce(u32, u64) -> u128>(f: F) { fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
@ -3746,13 +3746,13 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
@r###" @r###"
[57; 61) 'self': Self [57; 61) 'self': Self
[63; 67) 'args': Args [63; 67) 'args': Args
[132; 133) 'f': F [150; 151) 'f': F
[138; 166) '{ ...2)); }': () [156; 184) '{ ...2)); }': ()
[144; 145) 'f': F [162; 163) 'f': F
[144; 163) 'f.call...1, 2))': {unknown} [162; 181) 'f.call...1, 2))': {unknown}
[156; 162) '(1, 2)': (i32, i32) [174; 180) '(1, 2)': (u32, u64)
[157; 158) '1': i32 [175; 176) '1': u32
[160; 161) '2': i32 [178; 179) '2': u64
"### "###
); );
} }

View File

@ -2312,6 +2312,12 @@ impl PathSegment {
pub fn type_arg_list(&self) -> Option<TypeArgList> { pub fn type_arg_list(&self) -> Option<TypeArgList> {
AstChildren::new(&self.syntax).next() AstChildren::new(&self.syntax).next()
} }
pub fn param_list(&self) -> Option<ParamList> {
AstChildren::new(&self.syntax).next()
}
pub fn ret_type(&self) -> Option<RetType> {
AstChildren::new(&self.syntax).next()
}
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathType { pub struct PathType {

View File

@ -684,7 +684,7 @@ Grammar(
] ]
), ),
"PathSegment": ( "PathSegment": (
options: [ "NameRef", "TypeArgList" ] options: [ "NameRef", "TypeArgList", "ParamList", "RetType" ]
), ),
"TypeArgList": (collections: [ "TypeArgList": (collections: [
("type_args", "TypeArg"), ("type_args", "TypeArg"),