aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs38
1 files changed, 34 insertions, 4 deletions
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 {