aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-16 22:05:57 +0000
committerFlorian Diebold <[email protected]>2019-02-16 22:06:41 +0000
commita1bda3fc084bb6aa4979282b4907db9885fac9af (patch)
treede0f6864caba195ac3a0e463ab7a49e5adc66e8f /crates/ra_hir/src
parent65bd9bc3a800e09f52a315cf98e86c120c366c2c (diff)
Handle generic args for method calls
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/expr.rs9
-rw-r--r--crates/ra_hir/src/path.rs2
-rw-r--r--crates/ra_hir/src/ty.rs38
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap6
4 files changed, 45 insertions, 10 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 4e73590d0..e9db8282f 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -14,7 +14,7 @@ use crate::{
14 name::AsName, 14 name::AsName,
15 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeRef},
16}; 16};
17use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; 17use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}};
18 18
19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; 19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
20 20
@@ -193,6 +193,7 @@ pub enum Expr {
193 receiver: ExprId, 193 receiver: ExprId,
194 method_name: Name, 194 method_name: Name,
195 args: Vec<ExprId>, 195 args: Vec<ExprId>,
196 generic_args: Option<GenericArgs>,
196 }, 197 },
197 Match { 198 Match {
198 expr: ExprId, 199 expr: ExprId,
@@ -597,7 +598,11 @@ impl ExprCollector {
597 Vec::new() 598 Vec::new()
598 }; 599 };
599 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 600 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
600 self.alloc_expr(Expr::MethodCall { receiver, method_name, args }, syntax_ptr) 601 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast);
602 self.alloc_expr(
603 Expr::MethodCall { receiver, method_name, args, generic_args },
604 syntax_ptr,
605 )
601 } 606 }
602 ast::ExprKind::MatchExpr(e) => { 607 ast::ExprKind::MatchExpr(e) => {
603 let expr = self.collect_expr_opt(e.expr()); 608 let expr = self.collect_expr_opt(e.expr());
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 8ed54607a..83bbbb741 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -129,7 +129,7 @@ impl Path {
129} 129}
130 130
131impl GenericArgs { 131impl GenericArgs {
132 fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> { 132 pub fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> {
133 let mut args = Vec::new(); 133 let mut args = Vec::new();
134 for type_arg in node.type_args() { 134 for type_arg in node.type_args() {
135 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); 135 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index db0a20514..f32c77faf 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -165,6 +165,17 @@ impl Substs {
165 pub fn empty() -> Substs { 165 pub fn empty() -> Substs {
166 Substs(Arc::new([])) 166 Substs(Arc::new([]))
167 } 167 }
168
169 /// Replaces the end of the substitutions by other ones.
170 pub(crate) fn replace_tail(self, replace_by: Vec<Ty>) -> Substs {
171 // again missing Arc::make_mut_slice...
172 let len = replace_by.len().min(self.0.len());
173 let parent_len = self.0.len() - len;
174 let mut result = Vec::with_capacity(parent_len + len);
175 result.extend(self.0.iter().take(parent_len).cloned());
176 result.extend(replace_by);
177 Substs(result.into())
178 }
168} 179}
169 180
170/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 181/// 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> {
1367 } 1378 }
1368 ret_ty 1379 ret_ty
1369 } 1380 }
1370 Expr::MethodCall { receiver, args, method_name } => { 1381 Expr::MethodCall { receiver, args, method_name, generic_args } => {
1371 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 1382 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
1372 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 1383 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
1373 let method_ty = match resolved { 1384 let (method_ty, def_generics) = match resolved {
1374 Some(func) => { 1385 Some(func) => {
1375 self.write_method_resolution(tgt_expr, func); 1386 self.write_method_resolution(tgt_expr, func);
1376 self.db.type_for_def(func.into()) 1387 (self.db.type_for_def(func.into()), Some(func.generic_params(self.db)))
1388 }
1389 None => (Ty::Unknown, None),
1390 };
1391 // handle provided type arguments
1392 let method_ty = if let Some(generic_args) = generic_args {
1393 // if args are provided, it should be all of them, but we can't rely on that
1394 let param_count = def_generics.map(|g| g.params.len()).unwrap_or(0);
1395 let mut new_substs = Vec::with_capacity(generic_args.args.len());
1396 for arg in generic_args.args.iter().take(param_count) {
1397 match arg {
1398 GenericArg::Type(type_ref) => {
1399 let ty = self.make_ty(type_ref);
1400 new_substs.push(ty);
1401 }
1402 }
1377 } 1403 }
1378 None => Ty::Unknown, 1404 let substs = method_ty.substs().unwrap_or_else(Substs::empty);
1405 let substs = substs.replace_tail(new_substs);
1406 method_ty.apply_substs(substs)
1407 } else {
1408 method_ty
1379 }; 1409 };
1380 let method_ty = self.insert_type_vars(method_ty); 1410 let method_ty = self.insert_type_vars(method_ty);
1381 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1411 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap
index eabbe52fd..44f00a52e 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap
@@ -1,5 +1,5 @@
1--- 1---
2created: "2019-02-16T20:53:59.657979128Z" 2created: "2019-02-16T21:58:14.029368845Z"
3creator: [email protected] 3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs 4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result" 5expression: "&result"
@@ -34,6 +34,6 @@ expression: "&result"
34[309; 319) 'a.z(1i128)': (u64, i64, i128) 34[309; 319) 'a.z(1i128)': (u64, i64, i128)
35[313; 318) '1i128': i128 35[313; 318) '1i128': i128
36[325; 326) 'a': A<u64, i64> 36[325; 326) 'a': A<u64, i64>
37[325; 339) 'a.z::<u128>(1)': (u64, i64, i32) 37[325; 339) 'a.z::<u128>(1)': (u64, i64, u128)
38[337; 338) '1': i32 38[337; 338) '1': u128
39 39