Lower Fn(X, Y) -> Z
paths
This commit is contained in:
parent
60bdb66ef2
commit
d21cdf3c99
@ -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() }
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user