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 | |
parent | 65bd9bc3a800e09f52a315cf98e86c120c366c2c (diff) |
Handle generic args for method calls
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/path.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_impl_generics.snap | 6 |
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 | }; |
17 | use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; | 17 | use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}}; |
18 | 18 | ||
19 | pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; | 19 | pub 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 | ||
131 | impl GenericArgs { | 131 | impl 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 | --- |
2 | created: "2019-02-16T20:53:59.657979128Z" | 2 | created: "2019-02-16T21:58:14.029368845Z" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | source: crates/ra_hir/src/ty/tests.rs | 4 | source: crates/ra_hir/src/ty/tests.rs |
5 | expression: "&result" | 5 | expression: "&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 | ||