Handle generic args for method calls

This commit is contained in:
Florian Diebold 2019-02-16 23:05:57 +01:00
parent 65bd9bc3a8
commit a1bda3fc08
6 changed files with 50 additions and 11 deletions

View File

@ -14,7 +14,7 @@ use crate::{
name::AsName,
type_ref::{Mutability, TypeRef},
};
use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}};
pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
@ -193,6 +193,7 @@ pub enum Expr {
receiver: ExprId,
method_name: Name,
args: Vec<ExprId>,
generic_args: Option<GenericArgs>,
},
Match {
expr: ExprId,
@ -597,7 +598,11 @@ impl ExprCollector {
Vec::new()
};
let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
self.alloc_expr(Expr::MethodCall { receiver, method_name, args }, syntax_ptr)
let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
self.alloc_expr(
Expr::MethodCall { receiver, method_name, args, generic_args },
syntax_ptr,
)
}
ast::ExprKind::MatchExpr(e) => {
let expr = self.collect_expr_opt(e.expr());

View File

@ -129,7 +129,7 @@ impl Path {
}
impl GenericArgs {
fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> {
pub fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> {
let mut args = Vec::new();
for type_arg in node.type_args() {
let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());

View File

@ -165,6 +165,17 @@ impl Substs {
pub fn empty() -> Substs {
Substs(Arc::new([]))
}
/// Replaces the end of the substitutions by other ones.
pub(crate) fn replace_tail(self, replace_by: Vec<Ty>) -> Substs {
// again missing Arc::make_mut_slice...
let len = replace_by.len().min(self.0.len());
let parent_len = self.0.len() - len;
let mut result = Vec::with_capacity(parent_len + len);
result.extend(self.0.iter().take(parent_len).cloned());
result.extend(replace_by);
Substs(result.into())
}
}
/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
@ -1367,15 +1378,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
}
ret_ty
}
Expr::MethodCall { receiver, args, method_name } => {
Expr::MethodCall { receiver, args, method_name, generic_args } => {
let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
let method_ty = match resolved {
let (method_ty, def_generics) = match resolved {
Some(func) => {
self.write_method_resolution(tgt_expr, func);
self.db.type_for_def(func.into())
(self.db.type_for_def(func.into()), Some(func.generic_params(self.db)))
}
None => Ty::Unknown,
None => (Ty::Unknown, None),
};
// handle provided type arguments
let method_ty = if let Some(generic_args) = generic_args {
// if args are provided, it should be all of them, but we can't rely on that
let param_count = def_generics.map(|g| g.params.len()).unwrap_or(0);
let mut new_substs = Vec::with_capacity(generic_args.args.len());
for arg in generic_args.args.iter().take(param_count) {
match arg {
GenericArg::Type(type_ref) => {
let ty = self.make_ty(type_ref);
new_substs.push(ty);
}
}
}
let substs = method_ty.substs().unwrap_or_else(Substs::empty);
let substs = substs.replace_tail(new_substs);
method_ty.apply_substs(substs)
} else {
method_ty
};
let method_ty = self.insert_type_vars(method_ty);
let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {

View File

@ -1,5 +1,5 @@
---
created: "2019-02-16T20:53:59.657979128Z"
created: "2019-02-16T21:58:14.029368845Z"
creator: insta@0.6.2
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
@ -34,6 +34,6 @@ expression: "&result"
[309; 319) 'a.z(1i128)': (u64, i64, i128)
[313; 318) '1i128': i128
[325; 326) 'a': A<u64, i64>
[325; 339) 'a.z::<u128>(1)': (u64, i64, i32)
[337; 338) '1': i32
[325; 339) 'a.z::<u128>(1)': (u64, i64, u128)
[337; 338) '1': u128

View File

@ -2095,6 +2095,10 @@ impl MethodCallExpr {
pub fn name_ref(&self) -> Option<&NameRef> {
super::child_opt(self)
}
pub fn type_arg_list(&self) -> Option<&TypeArgList> {
super::child_opt(self)
}
}
// Module

View File

@ -431,7 +431,7 @@ Grammar(
),
"MethodCallExpr": (
traits: ["ArgListOwner"],
options: [ "Expr", "NameRef" ],
options: [ "Expr", "NameRef", "TypeArgList" ],
),
"IndexExpr": (),
"FieldExpr": (options: ["Expr", "NameRef"]),