diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 65 |
1 files changed, 52 insertions, 13 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index f28a7e731..562ad1f49 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). |
@@ -421,7 +432,8 @@ impl Ty { | |||
421 | (var.parent_enum(db).generic_params(db), segment) | 432 | (var.parent_enum(db).generic_params(db), segment) |
422 | } | 433 | } |
423 | }; | 434 | }; |
424 | // substs_from_path | 435 | let parent_param_count = def_generics.count_parent_params(); |
436 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); | ||
425 | if let Some(generic_args) = &segment.args_and_bindings { | 437 | if let Some(generic_args) = &segment.args_and_bindings { |
426 | // if args are provided, it should be all of them, but we can't rely on that | 438 | // if args are provided, it should be all of them, but we can't rely on that |
427 | let param_count = def_generics.params.len(); | 439 | let param_count = def_generics.params.len(); |
@@ -436,9 +448,8 @@ impl Ty { | |||
436 | } | 448 | } |
437 | // add placeholders for args that were not provided | 449 | // add placeholders for args that were not provided |
438 | // TODO: handle defaults | 450 | // TODO: handle defaults |
439 | let supplied_params = | 451 | let supplied_params = substs.len(); |
440 | segment.args_and_bindings.as_ref().map(|ga| ga.args.len()).unwrap_or(0); | 452 | for _ in supplied_params..def_generics.count_params_including_parent() { |
441 | for _ in supplied_params..def_generics.params.len() { | ||
442 | substs.push(Ty::Unknown); | 453 | substs.push(Ty::Unknown); |
443 | } | 454 | } |
444 | assert_eq!(substs.len(), def_generics.params.len()); | 455 | assert_eq!(substs.len(), def_generics.params.len()); |
@@ -666,7 +677,12 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | |||
666 | } | 677 | } |
667 | 678 | ||
668 | fn make_substs(generics: &GenericParams) -> Substs { | 679 | fn make_substs(generics: &GenericParams) -> Substs { |
669 | Substs(generics.params.iter().map(|_p| Ty::Unknown).collect::<Vec<_>>().into()) | 680 | Substs( |
681 | (0..generics.count_params_including_parent()) | ||
682 | .map(|_p| Ty::Unknown) | ||
683 | .collect::<Vec<_>>() | ||
684 | .into(), | ||
685 | ) | ||
670 | } | 686 | } |
671 | 687 | ||
672 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 688 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
@@ -1362,15 +1378,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1362 | } | 1378 | } |
1363 | ret_ty | 1379 | ret_ty |
1364 | } | 1380 | } |
1365 | Expr::MethodCall { receiver, args, method_name } => { | 1381 | Expr::MethodCall { receiver, args, method_name, generic_args } => { |
1366 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); | 1382 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); |
1367 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); | 1383 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); |
1368 | let method_ty = match resolved { | 1384 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { |
1369 | Some(func) => { | 1385 | Some((ty, func)) => { |
1370 | self.write_method_resolution(tgt_expr, func); | 1386 | self.write_method_resolution(tgt_expr, func); |
1371 | self.db.type_for_def(func.into()) | 1387 | (ty, self.db.type_for_def(func.into()), Some(func.generic_params(self.db))) |
1388 | } | ||
1389 | None => (Ty::Unknown, receiver_ty, 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 | } | ||
1372 | } | 1403 | } |
1373 | 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 | ||
1374 | }; | 1409 | }; |
1375 | let method_ty = self.insert_type_vars(method_ty); | 1410 | let method_ty = self.insert_type_vars(method_ty); |
1376 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | 1411 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { |
@@ -1394,9 +1429,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1394 | } | 1429 | } |
1395 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | 1430 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), |
1396 | }; | 1431 | }; |
1397 | // TODO we would have to apply the autoderef/autoref steps here | 1432 | // Apply autoref so the below unification works correctly |
1398 | // to get the correct receiver type to unify... | 1433 | let actual_receiver_ty = match expected_receiver_ty { |
1399 | self.unify(&expected_receiver_ty, &receiver_ty); | 1434 | Ty::Ref(_, mutability) => Ty::Ref(Arc::new(derefed_receiver_ty), mutability), |
1435 | _ => derefed_receiver_ty, | ||
1436 | }; | ||
1437 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | ||
1438 | |||
1400 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 1439 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
1401 | for (arg, param) in args.iter().zip(param_iter) { | 1440 | for (arg, param) in args.iter().zip(param_iter) { |
1402 | self.infer_expr(*arg, &Expectation::has_type(param)); | 1441 | self.infer_expr(*arg, &Expectation::has_type(param)); |