diff options
author | Florian Diebold <[email protected]> | 2019-02-16 22:05:57 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-16 22:06:41 +0000 |
commit | a1bda3fc084bb6aa4979282b4907db9885fac9af (patch) | |
tree | de0f6864caba195ac3a0e463ab7a49e5adc66e8f /crates/ra_hir/src/ty.rs | |
parent | 65bd9bc3a800e09f52a315cf98e86c120c366c2c (diff) |
Handle generic args for method calls
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 38 |
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 { |