From aa06893a1493770f8009d098a5340f1a9ba13dec Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Sat, 26 Jan 2019 00:30:56 +0100 Subject: Add type params to FnSignature --- crates/ra_hir/src/code_model_api.rs | 5 + crates/ra_hir/src/code_model_impl/function.rs | 2 + crates/ra_hir/src/generics.rs | 3 +- crates/ra_hir/src/ty.rs | 126 ++++++++------------- .../src/ty/snapshots/tests__infer_backwards.snap | 8 +- .../src/ty/snapshots/tests__infer_binary_op.snap | 8 +- .../snapshots/tests__infer_function_generics.snap | 30 ++--- .../ty/snapshots/tests__infer_generic_chain.snap | 52 ++++----- .../src/ty/snapshots/tests__infer_paths.snap | 10 +- 9 files changed, 107 insertions(+), 137 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index defb9fd0a..a13da58d2 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -388,6 +388,7 @@ pub use crate::code_model_impl::function::ScopeEntryWithSyntax; #[derive(Debug, Clone, PartialEq, Eq)] pub struct FnSignature { pub(crate) name: Name, + pub(crate) type_params: Arc, pub(crate) args: Vec, pub(crate) ret_type: TypeRef, /// True if the first param is `self`. This is relevant to decide whether this @@ -413,6 +414,10 @@ impl FnSignature { pub fn has_self_param(&self) -> bool { self.has_self_param } + + pub fn generics(&self) -> &GenericParams { + &self.type_params + } } impl Function { diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index b4aa18540..f4beab6ae 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -58,6 +58,7 @@ impl FnSignature { args.push(type_ref); } } + let type_params = db.generic_params(func.into()); let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { TypeRef::from_ast(type_ref) } else { @@ -66,6 +67,7 @@ impl FnSignature { let sig = FnSignature { name, + type_params, args, ret_type, has_self_param, diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index a5501d543..64c20a462 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -49,8 +49,7 @@ impl GenericParams { Arc::new(generics) } - // FIXME: probably shouldnt be pub(crate) - pub(crate) fn fill(&mut self, node: &impl TypeParamsOwner) { + fn fill(&mut self, node: &impl TypeParamsOwner) { if let Some(params) = node.type_param_list() { self.fill_params(params) } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 9b08b9c97..43181ffc9 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -20,6 +20,7 @@ mod tests; pub(crate) mod method_resolution; use std::borrow::Cow; +use std::iter::repeat; use std::ops::Index; use std::sync::Arc; use std::{fmt, mem}; @@ -225,7 +226,7 @@ pub enum Ty { /// For display name: Name, /// Substitutions for the generic parameters of the type - substs: Substs + substs: Substs, }, /// A pointer to a function. Written as `fn() -> i32`. @@ -543,11 +544,7 @@ impl Ty { name, substs, }, - Ty::FnDef { def, name, .. } => Ty::FnDef { - def, - name, - substs, - }, + Ty::FnDef { def, name, .. } => Ty::FnDef { def, name, substs }, _ => self, } } @@ -651,30 +648,10 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { Ty::FnDef { def: f.into(), name, - substs + substs, } } -fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { - let signature = f.signature(db); - let module = f.module(db); - let impl_block = f.impl_block(db); - let generics = f.generic_params(db); - let input = signature - .args() - .iter() - .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) - .collect::>(); - let output = Ty::from_hir( - db, - &module, - impl_block.as_ref(), - &generics, - signature.ret_type(), - ); - FnSig { input, output } -} - fn make_substs(generics: &GenericParams) -> Substs { Substs( generics @@ -946,9 +923,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.type_of_pat.insert(pat, ty); } - fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { - // TODO provide generics of function - let generics = GenericParams::default(); + fn make_ty(&mut self, type_ref: &TypeRef, generics: &GenericParams) -> Ty { let ty = Ty::from_hir( self.db, &self.module, @@ -1249,9 +1224,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::Tuple(ref tuple_args) => &**tuple_args, _ => &[], }; - let expectations_iter = expectations - .into_iter() - .chain(std::iter::repeat(&Ty::Unknown)); + let expectations_iter = expectations.into_iter().chain(repeat(&Ty::Unknown)); let inner_tys = args .iter() @@ -1370,7 +1343,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { let expected = if let Some(type_ref) = arg_type { - let ty = self.make_ty(type_ref); + let ty = self.make_ty(type_ref, &GenericParams::default()); ty } else { Ty::Unknown @@ -1386,22 +1359,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // TODO: we should use turbofish hints like this: // f::(x) let callee_ty = self.infer_expr(*callee, &Expectation::none()); - // FIXME: so manu unnecessary clones let (param_tys, ret_ty) = match &callee_ty { Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), Ty::FnDef { def, substs, .. } => { let fn_sig = def.signature(self.db); - // TODO: get input and return types from the fn_sig. - // it contains typerefs which we can make into proper tys - - let sig = get_func_sig(self.db, *def); - ( - sig.input - .iter() - .map(|ty| ty.clone().subst(&substs)) - .collect(), - sig.output.clone().subst(&substs), - ) + let ret_ty = self + .make_ty(fn_sig.ret_type(), fn_sig.generics()) + .subst(&substs); + let param_tys = fn_sig + .args() + .iter() + .map(|type_ref| { + self.make_ty(type_ref, fn_sig.generics()).subst(&substs) + }) + .collect(); + (param_tys, ret_ty) } _ => { // not callable @@ -1409,11 +1381,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { (Vec::new(), Ty::Unknown) } }; - for (i, arg) in args.iter().enumerate() { - self.infer_expr( - *arg, - &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), - ); + let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); + for (arg, param) in args.iter().zip(param_iter) { + self.infer_expr(*arg, &Expectation::has_type(param)); } ret_ty } @@ -1435,46 +1405,39 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { Ty::FnPtr(sig) => { if sig.input.len() > 0 { - (sig.input[0].clone(), sig.input[1..].iter().cloned().collect(), sig.output.clone()) + ( + sig.input[0].clone(), + sig.input[1..].iter().cloned().collect(), + sig.output.clone(), + ) } else { (Ty::Unknown, Vec::new(), sig.output.clone()) } } Ty::FnDef { def, substs, .. } => { - // TODO: fix deduplication with Expr::Call block above - // TODO: fix the ridiculous number of clones let fn_sig = def.signature(self.db); - // TODO: get input and return types from the fn_sig. - // it contains typerefs which we can make into proper tys - - // check that len > 0 - let sig = get_func_sig(self.db, *def); - if sig.input.len() > 0 { - ( - sig.input[0].clone().subst(&substs), - sig.input[1..] - .iter() - .map(|ty| ty.clone().subst(&substs)) - .collect(), - sig.output.clone().subst(&substs), - ) + let ret_ty = self + .make_ty(fn_sig.ret_type(), fn_sig.generics()) + .subst(&substs); + + if fn_sig.args().len() > 0 { + let mut arg_iter = fn_sig.args().iter().map(|type_ref| { + self.make_ty(type_ref, fn_sig.generics()).subst(&substs) + }); + let receiver_ty = arg_iter.next().unwrap(); + (receiver_ty, arg_iter.collect(), ret_ty) } else { - (Ty::Unknown, Vec::new(), sig.output.clone()) + (Ty::Unknown, Vec::new(), ret_ty) } } _ => (Ty::Unknown, Vec::new(), Ty::Unknown), }; // TODO we would have to apply the autoderef/autoref steps here // to get the correct receiver type to unify... - // - // TODO: zip param_tys.chain(iter::repeat(Ty::Unknown)) above then its not so bad - // that we clone self.unify(&expected_receiver_ty, &receiver_ty); - for (i, arg) in args.iter().enumerate() { - self.infer_expr( - *arg, - &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), - ); + let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); + for (arg, param) in args.iter().zip(param_iter) { + self.infer_expr(*arg, &Expectation::has_type(param)); } ret_ty } @@ -1558,7 +1521,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Expr::Cast { expr, type_ref } => { let _inner_ty = self.infer_expr(*expr, &Expectation::none()); - let cast_ty = self.make_ty(type_ref); + let cast_ty = self.make_ty(type_ref, &GenericParams::default()); // TODO check the cast... cast_ty } @@ -1672,7 +1635,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } => { let decl_ty = type_ref .as_ref() - .map(|tr| self.make_ty(tr)) + .map(|tr| self.make_ty(tr, &GenericParams::default())) .unwrap_or(Ty::Unknown); let decl_ty = self.insert_type_vars(decl_ty); let ty = if let Some(expr) = initializer { @@ -1699,12 +1662,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn collect_fn_signature(&mut self, signature: &FnSignature) { let body = Arc::clone(&self.body); // avoid borrow checker problem + let generics = signature.generics(); for (type_ref, pat) in signature.args().iter().zip(body.params()) { - let ty = self.make_ty(type_ref); + let ty = self.make_ty(type_ref, generics); self.infer_pat(*pat, &ty); } - self.return_ty = self.make_ty(signature.ret_type()); + self.return_ty = self.make_ty(signature.ret_type(), generics); } fn infer_body(&mut self) { diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap index 5c74bd8c7..e6b39f151 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap @@ -1,8 +1,8 @@ --- -created: "2019-01-22T14:44:59.880187500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.943309491+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [14; 15) 'x': u32 [22; 24) '{}': () @@ -10,7 +10,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs" [88; 89) 'a': u32 [92; 108) 'unknow...nction': [unknown] [92; 110) 'unknow...tion()': u32 -[116; 125) 'takes_u32': fn(u32) -> () +[116; 125) 'takes_u32': fn takes_u32 [116; 128) 'takes_u32(a)': () [126; 127) 'a': u32 [138; 139) 'b': i32 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap index c506bcadd..895c13ae6 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap @@ -1,8 +1,8 @@ --- -created: "2019-01-22T14:44:59.880187500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.949540810+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [6; 7) 'x': bool [22; 34) '{ 0i32 }': i32 @@ -28,7 +28,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs" [174; 196) 'minus_...ONST_2': bool [189; 196) 'CONST_2': isize [206; 207) 'c': i32 -[210; 211) 'f': fn(bool) -> i32 +[210; 211) 'f': fn f [210; 219) 'f(z || y)': i32 [210; 223) 'f(z || y) + 5': i32 [212; 213) 'z': bool diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap index 7203ad1e2..efe0e7adf 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap @@ -1,21 +1,21 @@ --- -created: "2019-01-22T14:44:59.954958500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.962273460+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- -[10; 11) 't': [unknown] -[21; 26) '{ t }': [unknown] -[23; 24) 't': [unknown] +[10; 11) 't': T +[21; 26) '{ t }': T +[23; 24) 't': T [38; 98) '{ ...(1); }': () -[44; 46) 'id': fn(T) -> T -[44; 52) 'id(1u32)': T +[44; 46) 'id': fn id +[44; 52) 'id(1u32)': u32 [47; 51) '1u32': u32 -[58; 68) 'id::': fn(T) -> T -[58; 71) 'id::(1)': T -[69; 70) '1': T -[81; 82) 'x': T -[90; 92) 'id': fn(T) -> T -[90; 95) 'id(1)': T -[93; 94) '1': T +[58; 68) 'id::': fn id +[58; 71) 'id::(1)': i32 +[69; 70) '1': i32 +[81; 82) 'x': u64 +[90; 92) 'id': fn id +[90; 95) 'id(1)': u64 +[93; 94) '1': u64 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap index 4435180a1..aaf8ccea5 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap @@ -1,36 +1,36 @@ --- -created: "2019-01-22T14:44:59.961936900+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.978506051+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [53; 57) 'self': A<[unknown]> [65; 87) '{ ... }': [unknown] [75; 79) 'self': A<[unknown]> [75; 81) 'self.x': [unknown] -[99; 100) 't': [unknown] -[110; 115) '{ t }': [unknown] -[112; 113) 't': [unknown] +[99; 100) 't': T +[110; 115) '{ t }': T +[112; 113) 't': T [135; 261) '{ ....x() }': i128 -[146; 147) 'x': T -[150; 151) '1': T -[162; 163) 'y': T -[166; 168) 'id': fn(T) -> T -[166; 171) 'id(x)': T -[169; 170) 'x': T -[182; 183) 'a': A -[186; 200) 'A { x: id(y) }': A -[193; 195) 'id': fn(T) -> T -[193; 198) 'id(y)': T -[196; 197) 'y': T -[211; 212) 'z': T -[215; 217) 'id': fn(T) -> T -[215; 222) 'id(a.x)': T -[218; 219) 'a': A -[218; 221) 'a.x': T -[233; 234) 'b': A -[237; 247) 'A { x: z }': A -[244; 245) 'z': T -[254; 255) 'b': A +[146; 147) 'x': i32 +[150; 151) '1': i32 +[162; 163) 'y': i32 +[166; 168) 'id': fn id +[166; 171) 'id(x)': i32 +[169; 170) 'x': i32 +[182; 183) 'a': A +[186; 200) 'A { x: id(y) }': A +[193; 195) 'id': fn id +[193; 198) 'id(y)': i32 +[196; 197) 'y': i32 +[211; 212) 'z': i32 +[215; 217) 'id': fn id +[215; 222) 'id(a.x)': i32 +[218; 219) 'a': A +[218; 221) 'a.x': i32 +[233; 234) 'b': A +[237; 247) 'A { x: z }': A +[244; 245) 'z': i32 +[254; 255) 'b': A [254; 259) 'b.x()': i128 diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap index 0bceffaef..efca36058 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap @@ -1,16 +1,16 @@ --- -created: "2019-01-22T14:44:59.975899500+00:00" -creator: insta@0.4.0 +created: "2019-01-25T23:18:54.985011010+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [15; 20) '{ 1 }': u32 [17; 18) '1': u32 [48; 53) '{ 1 }': u32 [50; 51) '1': u32 [67; 91) '{ ...c(); }': () -[73; 74) 'a': fn() -> u32 +[73; 74) 'a': fn a [73; 76) 'a()': u32 -[82; 86) 'b::c': fn() -> u32 +[82; 86) 'b::c': fn c [82; 88) 'b::c()': u32 -- cgit v1.2.3