diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-25 20:16:02 +0000 |
---|---|---|
committer | Marcus Klaas de Vries <[email protected]> | 2019-01-27 16:59:21 +0000 |
commit | 3bd47c0285433b5eb258196a81b95141d2a70505 (patch) | |
tree | 41bd19f6e95e4c22bd39c35702a1d2e048dd9cef /crates/ra_hir/src/ty.rs | |
parent | 3f4f50baaa21cb2d0f6c102f1ca521946071a8dc (diff) |
First attempt at generic type inference for fns
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 31ea45706..95de916ee 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -209,6 +209,18 @@ pub enum Ty { | |||
209 | /// `&'a mut T` or `&'a T`. | 209 | /// `&'a mut T` or `&'a T`. |
210 | Ref(Arc<Ty>, Mutability), | 210 | Ref(Arc<Ty>, Mutability), |
211 | 211 | ||
212 | /// The anonymous type of a function declaration/definition. Each | ||
213 | /// function has a unique type, which is output (for a function | ||
214 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
215 | /// | ||
216 | /// For example the type of `bar` here: | ||
217 | /// | ||
218 | /// ```rust | ||
219 | /// fn foo() -> i32 { 1 } | ||
220 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
221 | /// ``` | ||
222 | FnDef(Function, Substs), | ||
223 | |||
212 | /// A pointer to a function. Written as `fn() -> i32`. | 224 | /// A pointer to a function. Written as `fn() -> i32`. |
213 | /// | 225 | /// |
214 | /// For example the type of `bar` here: | 226 | /// For example the type of `bar` here: |
@@ -485,7 +497,7 @@ impl Ty { | |||
485 | } | 497 | } |
486 | sig_mut.output.walk_mut(f); | 498 | sig_mut.output.walk_mut(f); |
487 | } | 499 | } |
488 | Ty::Adt { substs, .. } => { | 500 | Ty::FnDef(_, substs) | Ty::Adt { substs, .. } => { |
489 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 501 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
490 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); | 502 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); |
491 | for t in &mut v { | 503 | for t in &mut v { |
@@ -524,6 +536,7 @@ impl Ty { | |||
524 | name, | 536 | name, |
525 | substs, | 537 | substs, |
526 | }, | 538 | }, |
539 | Ty::FnDef(func, _) => Ty::FnDef(func, substs), | ||
527 | _ => self, | 540 | _ => self, |
528 | } | 541 | } |
529 | } | 542 | } |
@@ -579,6 +592,7 @@ impl fmt::Display for Ty { | |||
579 | .to_fmt(f) | 592 | .to_fmt(f) |
580 | } | 593 | } |
581 | } | 594 | } |
595 | Ty::FnDef(_func, _substs) => write!(f, "FNDEF-IMPLEMENT-ME"), | ||
582 | Ty::FnPtr(sig) => { | 596 | Ty::FnPtr(sig) => { |
583 | join(sig.input.iter()) | 597 | join(sig.input.iter()) |
584 | .surround_with("fn(", ")") | 598 | .surround_with("fn(", ")") |
@@ -608,12 +622,18 @@ impl fmt::Display for Ty { | |||
608 | /// Compute the declared type of a function. This should not need to look at the | 622 | /// Compute the declared type of a function. This should not need to look at the |
609 | /// function body. | 623 | /// function body. |
610 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | 624 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { |
625 | let generics = f.generic_params(db); | ||
626 | let substs = make_substs(&generics); | ||
627 | Ty::FnDef(f.into(), substs) | ||
628 | } | ||
629 | |||
630 | fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { | ||
611 | let signature = f.signature(db); | 631 | let signature = f.signature(db); |
612 | let module = f.module(db); | 632 | let module = f.module(db); |
613 | let impl_block = f.impl_block(db); | 633 | let impl_block = f.impl_block(db); |
614 | let generics = f.generic_params(db); | 634 | let generics = f.generic_params(db); |
615 | let input = signature | 635 | let input = signature |
616 | .params() | 636 | .args() |
617 | .iter() | 637 | .iter() |
618 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) | 638 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) |
619 | .collect::<Vec<_>>(); | 639 | .collect::<Vec<_>>(); |
@@ -624,8 +644,7 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | |||
624 | &generics, | 644 | &generics, |
625 | signature.ret_type(), | 645 | signature.ret_type(), |
626 | ); | 646 | ); |
627 | let sig = FnSig { input, output }; | 647 | FnSig { input, output } |
628 | Ty::FnPtr(Arc::new(sig)) | ||
629 | } | 648 | } |
630 | 649 | ||
631 | fn make_substs(generics: &GenericParams) -> Substs { | 650 | fn make_substs(generics: &GenericParams) -> Substs { |
@@ -1142,7 +1161,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1142 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1161 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1143 | (ty, Some(var.into())) | 1162 | (ty, Some(var.into())) |
1144 | } | 1163 | } |
1145 | TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), | 1164 | TypableDef::Function(func) => { |
1165 | let ty = type_for_fn(self.db, func); | ||
1166 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
1167 | // FIXME: is this right? | ||
1168 | (ty, None) | ||
1169 | } | ||
1170 | TypableDef::Enum(_) => (Ty::Unknown, None), | ||
1146 | } | 1171 | } |
1147 | } | 1172 | } |
1148 | 1173 | ||
@@ -1331,12 +1356,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1331 | } | 1356 | } |
1332 | Expr::Call { callee, args } => { | 1357 | Expr::Call { callee, args } => { |
1333 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | 1358 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); |
1359 | // FIXME: so manu unnecessary clones | ||
1334 | let (param_tys, ret_ty) = match &callee_ty { | 1360 | let (param_tys, ret_ty) = match &callee_ty { |
1335 | Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), | 1361 | Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), |
1362 | Ty::FnDef(func, substs) => { | ||
1363 | let fn_sig = func.signature(self.db); | ||
1364 | // TODO: get input and return types from the fn_sig. | ||
1365 | // it contains typerefs which we can make into proper tys | ||
1366 | |||
1367 | let sig = get_func_sig(self.db, *func); | ||
1368 | ( | ||
1369 | sig.input | ||
1370 | .iter() | ||
1371 | .map(|ty| ty.clone().subst(&substs)) | ||
1372 | .collect(), | ||
1373 | sig.output.clone().subst(&substs), | ||
1374 | ) | ||
1375 | } | ||
1336 | _ => { | 1376 | _ => { |
1337 | // not callable | 1377 | // not callable |
1338 | // TODO report an error? | 1378 | // TODO report an error? |
1339 | (&[][..], Ty::Unknown) | 1379 | (Vec::new(), Ty::Unknown) |
1340 | } | 1380 | } |
1341 | }; | 1381 | }; |
1342 | for (i, arg) in args.iter().enumerate() { | 1382 | for (i, arg) in args.iter().enumerate() { |
@@ -1604,15 +1644,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1604 | 1644 | ||
1605 | fn collect_fn_signature(&mut self, signature: &FnSignature) { | 1645 | fn collect_fn_signature(&mut self, signature: &FnSignature) { |
1606 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 1646 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
1607 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { | 1647 | for (type_ref, pat) in signature.args().iter().zip(body.params()) { |
1608 | let ty = self.make_ty(type_ref); | 1648 | let ty = self.make_ty(type_ref); |
1609 | 1649 | ||
1610 | self.infer_pat(*pat, &ty); | 1650 | self.infer_pat(*pat, &ty); |
1611 | } | 1651 | } |
1612 | self.return_ty = { | 1652 | self.return_ty = self.make_ty(signature.ret_type()); |
1613 | let ty = self.make_ty(signature.ret_type()); | ||
1614 | ty | ||
1615 | }; | ||
1616 | } | 1653 | } |
1617 | 1654 | ||
1618 | fn infer_body(&mut self) { | 1655 | fn infer_body(&mut self) { |