diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 544 |
1 files changed, 228 insertions, 316 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index b685259d7..6bdfdd7b4 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -17,6 +17,7 @@ mod primitive; | |||
17 | #[cfg(test)] | 17 | #[cfg(test)] |
18 | mod tests; | 18 | mod tests; |
19 | 19 | ||
20 | use std::ops::Index; | ||
20 | use std::sync::Arc; | 21 | use std::sync::Arc; |
21 | use std::{fmt, mem}; | 22 | use std::{fmt, mem}; |
22 | 23 | ||
@@ -24,18 +25,15 @@ use log; | |||
24 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
25 | use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; | 26 | use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; |
26 | 27 | ||
27 | use ra_db::{LocalSyntaxPtr, Cancelable}; | 28 | use ra_db::Cancelable; |
28 | use ra_syntax::{ | ||
29 | ast::{self, AstNode, LoopBodyOwner, ArgListOwner, PrefixOp, BinOp}, | ||
30 | SyntaxNodeRef | ||
31 | }; | ||
32 | 29 | ||
33 | use crate::{ | 30 | use crate::{ |
34 | Def, DefId, Module, Function, Struct, Enum, Path, Name, AsName, ImplBlock, | 31 | Def, DefId, Module, Function, Struct, Enum, Path, Name, ImplBlock, |
32 | FnSignature, FnScopes, | ||
35 | db::HirDatabase, | 33 | db::HirDatabase, |
36 | type_ref::{TypeRef, Mutability}, | 34 | type_ref::{TypeRef, Mutability}, |
37 | name::KnownName, | 35 | name::KnownName, |
38 | ScopesWithSyntaxMapping, | 36 | expr::{Body, Expr, ExprId, PatId, UnaryOp, BinaryOp, Statement}, |
39 | }; | 37 | }; |
40 | 38 | ||
41 | /// The ID of a type variable. | 39 | /// The ID of a type variable. |
@@ -82,9 +80,10 @@ impl UnifyValue for TypeVarValue { | |||
82 | match (value1, value2) { | 80 | match (value1, value2) { |
83 | // We should never equate two type variables, both of which have | 81 | // We should never equate two type variables, both of which have |
84 | // known types. Instead, we recursively equate those types. | 82 | // known types. Instead, we recursively equate those types. |
85 | (TypeVarValue::Known(..), TypeVarValue::Known(..)) => { | 83 | (TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!( |
86 | panic!("equating two type variables, both of which have known types") | 84 | "equating two type variables, both of which have known types: {:?} and {:?}", |
87 | } | 85 | t1, t2 |
86 | ), | ||
88 | 87 | ||
89 | // If one side is known, prefer that one. | 88 | // If one side is known, prefer that one. |
90 | (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()), | 89 | (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()), |
@@ -321,26 +320,6 @@ impl Ty { | |||
321 | Ok(ty) | 320 | Ok(ty) |
322 | } | 321 | } |
323 | 322 | ||
324 | // TODO: These should not be necessary long-term, since everything will work on HIR | ||
325 | pub(crate) fn from_ast_opt( | ||
326 | db: &impl HirDatabase, | ||
327 | module: &Module, | ||
328 | impl_block: Option<&ImplBlock>, | ||
329 | node: Option<ast::TypeRef>, | ||
330 | ) -> Cancelable<Self> { | ||
331 | node.map(|n| Ty::from_ast(db, module, impl_block, n)) | ||
332 | .unwrap_or(Ok(Ty::Unknown)) | ||
333 | } | ||
334 | |||
335 | pub(crate) fn from_ast( | ||
336 | db: &impl HirDatabase, | ||
337 | module: &Module, | ||
338 | impl_block: Option<&ImplBlock>, | ||
339 | node: ast::TypeRef, | ||
340 | ) -> Cancelable<Self> { | ||
341 | Ty::from_hir(db, module, impl_block, &TypeRef::from_ast(node)) | ||
342 | } | ||
343 | |||
344 | pub fn unit() -> Self { | 323 | pub fn unit() -> Self { |
345 | Ty::Tuple(Arc::new([])) | 324 | Ty::Tuple(Arc::new([])) |
346 | } | 325 | } |
@@ -417,26 +396,18 @@ impl fmt::Display for Ty { | |||
417 | // Functions returning declared types for items | 396 | // Functions returning declared types for items |
418 | 397 | ||
419 | /// Compute the declared type of a function. This should not need to look at the | 398 | /// Compute the declared type of a function. This should not need to look at the |
420 | /// function body (but currently uses the function AST, so does anyway - TODO). | 399 | /// function body. |
421 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { | 400 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { |
422 | let syntax = f.syntax(db); | 401 | let signature = f.signature(db); |
423 | let module = f.module(db)?; | 402 | let module = f.module(db)?; |
424 | let impl_block = f.impl_block(db)?; | 403 | let impl_block = f.impl_block(db)?; |
425 | let node = syntax.borrowed(); | ||
426 | // TODO we ignore type parameters for now | 404 | // TODO we ignore type parameters for now |
427 | let input = node | 405 | let input = signature |
428 | .param_list() | 406 | .args() |
429 | .map(|pl| { | 407 | .iter() |
430 | pl.params() | 408 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr)) |
431 | .map(|p| Ty::from_ast_opt(db, &module, impl_block.as_ref(), p.type_ref())) | 409 | .collect::<Cancelable<Vec<_>>>()?; |
432 | .collect() | 410 | let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type())?; |
433 | }) | ||
434 | .unwrap_or_else(|| Ok(Vec::new()))?; | ||
435 | let output = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { | ||
436 | Ty::from_ast(db, &module, impl_block.as_ref(), type_ref)? | ||
437 | } else { | ||
438 | Ty::unit() | ||
439 | }; | ||
440 | let sig = FnSig { input, output }; | 411 | let sig = FnSig { input, output }; |
441 | Ok(Ty::FnPtr(Arc::new(sig))) | 412 | Ok(Ty::FnPtr(Arc::new(sig))) |
442 | } | 413 | } |
@@ -499,16 +470,23 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) | |||
499 | /// The result of type inference: A mapping from expressions and patterns to types. | 470 | /// The result of type inference: A mapping from expressions and patterns to types. |
500 | #[derive(Clone, PartialEq, Eq, Debug)] | 471 | #[derive(Clone, PartialEq, Eq, Debug)] |
501 | pub struct InferenceResult { | 472 | pub struct InferenceResult { |
502 | type_of: FxHashMap<LocalSyntaxPtr, Ty>, | 473 | type_of_expr: FxHashMap<ExprId, Ty>, |
474 | type_of_pat: FxHashMap<PatId, Ty>, | ||
503 | } | 475 | } |
504 | 476 | ||
505 | impl InferenceResult { | 477 | impl Index<ExprId> for InferenceResult { |
506 | /// Returns the type of the given syntax node, if it was inferred. Will | 478 | type Output = Ty; |
507 | /// return `None` for syntax nodes not in the inferred function or not | 479 | |
508 | /// pointing to an expression/pattern, `Some(Ty::Unknown)` for | 480 | fn index(&self, expr: ExprId) -> &Ty { |
509 | /// expressions/patterns that could not be inferred. | 481 | self.type_of_expr.get(&expr).unwrap_or(&Ty::Unknown) |
510 | pub fn type_of_node(&self, node: SyntaxNodeRef) -> Option<Ty> { | 482 | } |
511 | self.type_of.get(&LocalSyntaxPtr::new(node)).cloned() | 483 | } |
484 | |||
485 | impl Index<PatId> for InferenceResult { | ||
486 | type Output = Ty; | ||
487 | |||
488 | fn index(&self, pat: PatId) -> &Ty { | ||
489 | self.type_of_pat.get(&pat).unwrap_or(&Ty::Unknown) | ||
512 | } | 490 | } |
513 | } | 491 | } |
514 | 492 | ||
@@ -516,44 +494,46 @@ impl InferenceResult { | |||
516 | #[derive(Clone, Debug)] | 494 | #[derive(Clone, Debug)] |
517 | struct InferenceContext<'a, D: HirDatabase> { | 495 | struct InferenceContext<'a, D: HirDatabase> { |
518 | db: &'a D, | 496 | db: &'a D, |
519 | scopes: ScopesWithSyntaxMapping, | 497 | body: Arc<Body>, |
520 | /// The self param for the current method, if it exists. | 498 | scopes: Arc<FnScopes>, |
521 | self_param: Option<LocalSyntaxPtr>, | ||
522 | module: Module, | 499 | module: Module, |
523 | impl_block: Option<ImplBlock>, | 500 | impl_block: Option<ImplBlock>, |
524 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 501 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
525 | type_of: FxHashMap<LocalSyntaxPtr, Ty>, | 502 | type_of_expr: FxHashMap<ExprId, Ty>, |
503 | type_of_pat: FxHashMap<PatId, Ty>, | ||
526 | /// The return type of the function being inferred. | 504 | /// The return type of the function being inferred. |
527 | return_ty: Ty, | 505 | return_ty: Ty, |
528 | } | 506 | } |
529 | 507 | ||
530 | // helper function that determines whether a binary operator | 508 | // helper function that determines whether a binary operator |
531 | // always returns a boolean | 509 | // always returns a boolean |
532 | fn is_boolean_operator(op: BinOp) -> bool { | 510 | fn is_boolean_operator(op: BinaryOp) -> bool { |
533 | match op { | 511 | match op { |
534 | BinOp::BooleanOr | 512 | BinaryOp::BooleanOr |
535 | | BinOp::BooleanAnd | 513 | | BinaryOp::BooleanAnd |
536 | | BinOp::EqualityTest | 514 | | BinaryOp::EqualityTest |
537 | | BinOp::LesserEqualTest | 515 | | BinaryOp::LesserEqualTest |
538 | | BinOp::GreaterEqualTest | 516 | | BinaryOp::GreaterEqualTest |
539 | | BinOp::LesserTest | 517 | | BinaryOp::LesserTest |
540 | | BinOp::GreaterTest => true, | 518 | | BinaryOp::GreaterTest => true, |
541 | } | 519 | } |
542 | } | 520 | } |
543 | 521 | ||
544 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 522 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
545 | fn new( | 523 | fn new( |
546 | db: &'a D, | 524 | db: &'a D, |
547 | scopes: ScopesWithSyntaxMapping, | 525 | body: Arc<Body>, |
526 | scopes: Arc<FnScopes>, | ||
548 | module: Module, | 527 | module: Module, |
549 | impl_block: Option<ImplBlock>, | 528 | impl_block: Option<ImplBlock>, |
550 | ) -> Self { | 529 | ) -> Self { |
551 | InferenceContext { | 530 | InferenceContext { |
552 | type_of: FxHashMap::default(), | 531 | type_of_expr: FxHashMap::default(), |
532 | type_of_pat: FxHashMap::default(), | ||
553 | var_unification_table: InPlaceUnificationTable::new(), | 533 | var_unification_table: InPlaceUnificationTable::new(), |
554 | self_param: None, // set during parameter typing | ||
555 | return_ty: Ty::Unknown, // set in collect_fn_signature | 534 | return_ty: Ty::Unknown, // set in collect_fn_signature |
556 | db, | 535 | db, |
536 | body, | ||
557 | scopes, | 537 | scopes, |
558 | module, | 538 | module, |
559 | impl_block, | 539 | impl_block, |
@@ -561,24 +541,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
561 | } | 541 | } |
562 | 542 | ||
563 | fn resolve_all(mut self) -> InferenceResult { | 543 | fn resolve_all(mut self) -> InferenceResult { |
564 | let mut types = mem::replace(&mut self.type_of, FxHashMap::default()); | 544 | let mut expr_types = mem::replace(&mut self.type_of_expr, FxHashMap::default()); |
565 | for ty in types.values_mut() { | 545 | for ty in expr_types.values_mut() { |
546 | let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); | ||
547 | *ty = resolved; | ||
548 | } | ||
549 | let mut pat_types = mem::replace(&mut self.type_of_pat, FxHashMap::default()); | ||
550 | for ty in pat_types.values_mut() { | ||
566 | let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); | 551 | let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); |
567 | *ty = resolved; | 552 | *ty = resolved; |
568 | } | 553 | } |
569 | InferenceResult { type_of: types } | 554 | InferenceResult { |
555 | type_of_expr: expr_types, | ||
556 | type_of_pat: pat_types, | ||
557 | } | ||
570 | } | 558 | } |
571 | 559 | ||
572 | fn write_ty(&mut self, node: SyntaxNodeRef, ty: Ty) { | 560 | fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) { |
573 | self.type_of.insert(LocalSyntaxPtr::new(node), ty); | 561 | self.type_of_expr.insert(expr, ty); |
574 | } | 562 | } |
575 | 563 | ||
576 | fn make_ty(&self, type_ref: &TypeRef) -> Cancelable<Ty> { | 564 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { |
577 | Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) | 565 | self.type_of_pat.insert(pat, ty); |
578 | } | 566 | } |
579 | 567 | ||
580 | fn make_ty_opt(&self, type_ref: Option<&TypeRef>) -> Cancelable<Ty> { | 568 | fn make_ty(&self, type_ref: &TypeRef) -> Cancelable<Ty> { |
581 | Ty::from_hir_opt(self.db, &self.module, self.impl_block.as_ref(), type_ref) | 569 | Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) |
582 | } | 570 | } |
583 | 571 | ||
584 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 572 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
@@ -673,23 +661,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
673 | }) | 661 | }) |
674 | } | 662 | } |
675 | 663 | ||
676 | fn infer_path_expr(&mut self, expr: ast::PathExpr) -> Cancelable<Option<Ty>> { | 664 | fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Cancelable<Option<Ty>> { |
677 | let ast_path = ctry!(expr.path()); | 665 | if path.is_ident() || path.is_self() { |
678 | let path = ctry!(Path::from_ast(ast_path)); | ||
679 | if path.is_ident() { | ||
680 | // resolve locally | 666 | // resolve locally |
681 | let name = ctry!(ast_path.segment().and_then(|s| s.name_ref())); | 667 | let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); |
682 | if let Some(scope_entry) = self.scopes.resolve_local_name(name) { | 668 | if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { |
683 | let ty = ctry!(self.type_of.get(&scope_entry.ptr())); | 669 | let ty = ctry!(self.type_of_pat.get(&scope_entry.pat())); |
684 | let ty = self.resolve_ty_as_possible(ty.clone()); | 670 | let ty = self.resolve_ty_as_possible(ty.clone()); |
685 | return Ok(Some(ty)); | 671 | return Ok(Some(ty)); |
686 | }; | 672 | }; |
687 | } else if path.is_self() { | ||
688 | // resolve `self` param | ||
689 | let self_param = ctry!(self.self_param); | ||
690 | let ty = ctry!(self.type_of.get(&self_param)); | ||
691 | let ty = self.resolve_ty_as_possible(ty.clone()); | ||
692 | return Ok(Some(ty)); | ||
693 | }; | 673 | }; |
694 | 674 | ||
695 | // resolve in module | 675 | // resolve in module |
@@ -699,8 +679,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
699 | Ok(Some(ty)) | 679 | Ok(Some(ty)) |
700 | } | 680 | } |
701 | 681 | ||
702 | fn resolve_variant(&self, path: Option<ast::Path>) -> Cancelable<(Ty, Option<DefId>)> { | 682 | fn resolve_variant(&self, path: Option<&Path>) -> Cancelable<(Ty, Option<DefId>)> { |
703 | let path = if let Some(path) = path.and_then(Path::from_ast) { | 683 | let path = if let Some(path) = path { |
704 | path | 684 | path |
705 | } else { | 685 | } else { |
706 | return Ok((Ty::Unknown, None)); | 686 | return Ok((Ty::Unknown, None)); |
@@ -719,74 +699,51 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
719 | }) | 699 | }) |
720 | } | 700 | } |
721 | 701 | ||
722 | fn infer_expr_opt( | 702 | fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Cancelable<Ty> { |
723 | &mut self, | 703 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
724 | expr: Option<ast::Expr>, | 704 | let ty = match &body[expr] { |
725 | expected: &Expectation, | 705 | Expr::Missing => Ty::Unknown, |
726 | ) -> Cancelable<Ty> { | 706 | Expr::If { |
727 | if let Some(e) = expr { | 707 | condition, |
728 | self.infer_expr(e, expected) | 708 | then_branch, |
729 | } else { | 709 | else_branch, |
730 | Ok(Ty::Unknown) | 710 | } => { |
731 | } | 711 | // if let is desugared to match, so this is always simple if |
732 | } | 712 | self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; |
733 | 713 | let then_ty = self.infer_expr(*then_branch, expected)?; | |
734 | fn infer_expr(&mut self, expr: ast::Expr, expected: &Expectation) -> Cancelable<Ty> { | 714 | if let Some(else_branch) = else_branch { |
735 | let ty = match expr { | 715 | self.infer_expr(*else_branch, expected)?; |
736 | ast::Expr::IfExpr(e) => { | ||
737 | if let Some(condition) = e.condition() { | ||
738 | let expected = if condition.pat().is_none() { | ||
739 | Expectation::has_type(Ty::Bool) | ||
740 | } else { | ||
741 | Expectation::none() | ||
742 | }; | ||
743 | self.infer_expr_opt(condition.expr(), &expected)?; | ||
744 | // TODO write type for pat | ||
745 | }; | ||
746 | let if_ty = self.infer_block_opt(e.then_branch(), expected)?; | ||
747 | if let Some(else_branch) = e.else_branch() { | ||
748 | self.infer_block(else_branch, expected)?; | ||
749 | } else { | 716 | } else { |
750 | // no else branch -> unit | 717 | // no else branch -> unit |
751 | self.unify(&expected.ty, &Ty::unit()); // actually coerce | 718 | self.unify(&expected.ty, &Ty::unit()); // actually coerce |
752 | } | 719 | } |
753 | if_ty | 720 | then_ty |
754 | } | 721 | } |
755 | ast::Expr::BlockExpr(e) => self.infer_block_opt(e.block(), expected)?, | 722 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected)?, |
756 | ast::Expr::LoopExpr(e) => { | 723 | Expr::Loop { body } => { |
757 | self.infer_block_opt(e.loop_body(), &Expectation::has_type(Ty::unit()))?; | 724 | self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; |
758 | // TODO never, or the type of the break param | 725 | // TODO handle break with value |
759 | Ty::Unknown | 726 | Ty::Never |
760 | } | 727 | } |
761 | ast::Expr::WhileExpr(e) => { | 728 | Expr::While { condition, body } => { |
762 | if let Some(condition) = e.condition() { | 729 | // while let is desugared to a match loop, so this is always simple while |
763 | let expected = if condition.pat().is_none() { | 730 | self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; |
764 | Expectation::has_type(Ty::Bool) | 731 | self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; |
765 | } else { | ||
766 | Expectation::none() | ||
767 | }; | ||
768 | self.infer_expr_opt(condition.expr(), &expected)?; | ||
769 | // TODO write type for pat | ||
770 | }; | ||
771 | self.infer_block_opt(e.loop_body(), &Expectation::has_type(Ty::unit()))?; | ||
772 | // TODO always unit? | ||
773 | Ty::unit() | 732 | Ty::unit() |
774 | } | 733 | } |
775 | ast::Expr::ForExpr(e) => { | 734 | Expr::For { iterable, body, .. } => { |
776 | let _iterable_ty = self.infer_expr_opt(e.iterable(), &Expectation::none()); | 735 | let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); |
777 | if let Some(_pat) = e.pat() { | 736 | // TODO write type for pat |
778 | // TODO write type for pat | 737 | self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; |
779 | } | ||
780 | self.infer_block_opt(e.loop_body(), &Expectation::has_type(Ty::unit()))?; | ||
781 | // TODO always unit? | ||
782 | Ty::unit() | 738 | Ty::unit() |
783 | } | 739 | } |
784 | ast::Expr::LambdaExpr(e) => { | 740 | Expr::Lambda { body, .. } => { |
785 | let _body_ty = self.infer_expr_opt(e.body(), &Expectation::none())?; | 741 | // TODO write types for args, infer lambda type etc. |
742 | let _body_ty = self.infer_expr(*body, &Expectation::none())?; | ||
786 | Ty::Unknown | 743 | Ty::Unknown |
787 | } | 744 | } |
788 | ast::Expr::CallExpr(e) => { | 745 | Expr::Call { callee, args } => { |
789 | let callee_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 746 | let callee_ty = self.infer_expr(*callee, &Expectation::none())?; |
790 | let (arg_tys, ret_ty) = match &callee_ty { | 747 | let (arg_tys, ret_ty) = match &callee_ty { |
791 | Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), | 748 | Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), |
792 | _ => { | 749 | _ => { |
@@ -795,112 +752,102 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
795 | (&[][..], Ty::Unknown) | 752 | (&[][..], Ty::Unknown) |
796 | } | 753 | } |
797 | }; | 754 | }; |
798 | if let Some(arg_list) = e.arg_list() { | 755 | for (i, arg) in args.iter().enumerate() { |
799 | for (i, arg) in arg_list.args().enumerate() { | 756 | self.infer_expr( |
800 | self.infer_expr( | 757 | *arg, |
801 | arg, | 758 | &Expectation::has_type(arg_tys.get(i).cloned().unwrap_or(Ty::Unknown)), |
802 | &Expectation::has_type(arg_tys.get(i).cloned().unwrap_or(Ty::Unknown)), | 759 | )?; |
803 | )?; | ||
804 | } | ||
805 | } | 760 | } |
806 | ret_ty | 761 | ret_ty |
807 | } | 762 | } |
808 | ast::Expr::MethodCallExpr(e) => { | 763 | Expr::MethodCall { receiver, args, .. } => { |
809 | let _receiver_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 764 | let _receiver_ty = self.infer_expr(*receiver, &Expectation::none())?; |
810 | if let Some(arg_list) = e.arg_list() { | 765 | // TODO resolve method... |
811 | for arg in arg_list.args() { | 766 | for (_i, arg) in args.iter().enumerate() { |
812 | // TODO unify / expect argument type | 767 | // TODO unify / expect argument type |
813 | self.infer_expr(arg, &Expectation::none())?; | 768 | self.infer_expr(*arg, &Expectation::none())?; |
814 | } | ||
815 | } | 769 | } |
816 | Ty::Unknown | 770 | Ty::Unknown |
817 | } | 771 | } |
818 | ast::Expr::MatchExpr(e) => { | 772 | Expr::Match { expr, arms } => { |
819 | let _ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 773 | let _ty = self.infer_expr(*expr, &Expectation::none())?; |
820 | if let Some(match_arm_list) = e.match_arm_list() { | 774 | for arm in arms { |
821 | for arm in match_arm_list.arms() { | 775 | // TODO type the bindings in pats |
822 | // TODO type the bindings in pat | 776 | // TODO type the guard |
823 | // TODO type the guard | 777 | let _ty = self.infer_expr(arm.expr, &Expectation::none())?; |
824 | let _ty = self.infer_expr_opt(arm.expr(), &Expectation::none())?; | ||
825 | } | ||
826 | // TODO unify all the match arm types | ||
827 | Ty::Unknown | ||
828 | } else { | ||
829 | Ty::Unknown | ||
830 | } | 778 | } |
779 | // TODO unify all the match arm types | ||
780 | Ty::Unknown | ||
831 | } | 781 | } |
832 | ast::Expr::TupleExpr(_e) => Ty::Unknown, | 782 | Expr::Path(p) => self.infer_path_expr(expr, p)?.unwrap_or(Ty::Unknown), |
833 | ast::Expr::ArrayExpr(_e) => Ty::Unknown, | 783 | Expr::Continue => Ty::Never, |
834 | ast::Expr::PathExpr(e) => self.infer_path_expr(e)?.unwrap_or(Ty::Unknown), | 784 | Expr::Break { expr } => { |
835 | ast::Expr::ContinueExpr(_e) => Ty::Never, | 785 | if let Some(expr) = expr { |
836 | ast::Expr::BreakExpr(_e) => Ty::Never, | 786 | // TODO handle break with value |
837 | ast::Expr::ParenExpr(e) => self.infer_expr_opt(e.expr(), expected)?, | 787 | self.infer_expr(*expr, &Expectation::none())?; |
838 | ast::Expr::Label(_e) => Ty::Unknown, | 788 | } |
839 | ast::Expr::ReturnExpr(e) => { | ||
840 | // TODO expect return type of function | ||
841 | self.infer_expr_opt(e.expr(), &Expectation::none())?; | ||
842 | Ty::Never | 789 | Ty::Never |
843 | } | 790 | } |
844 | ast::Expr::StructLit(e) => { | 791 | Expr::Return { expr } => { |
845 | let (ty, def_id) = self.resolve_variant(e.path())?; | 792 | if let Some(expr) = expr { |
846 | if let Some(nfl) = e.named_field_list() { | 793 | self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone()))?; |
847 | for field in nfl.fields() { | ||
848 | let field_ty = if let (Some(def_id), Some(nr)) = (def_id, field.name_ref()) | ||
849 | { | ||
850 | self.db.type_for_field(def_id, nr.as_name())? | ||
851 | } else { | ||
852 | Ty::Unknown | ||
853 | }; | ||
854 | self.infer_expr_opt(field.expr(), &Expectation::has_type(field_ty))?; | ||
855 | } | ||
856 | } | 794 | } |
857 | ty | 795 | Ty::Never |
858 | } | 796 | } |
859 | ast::Expr::IndexExpr(_e) => Ty::Unknown, | 797 | Expr::StructLit { |
860 | ast::Expr::FieldExpr(e) => { | 798 | path, |
861 | let receiver_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 799 | fields, |
862 | if let Some(nr) = e.name_ref() { | 800 | spread, |
863 | let ty = match receiver_ty { | 801 | } => { |
864 | Ty::Tuple(fields) => { | 802 | let (ty, def_id) = self.resolve_variant(path.as_ref())?; |
865 | let i = nr.text().parse::<usize>().ok(); | 803 | for field in fields { |
866 | i.and_then(|i| fields.get(i).cloned()) | 804 | let field_ty = if let Some(def_id) = def_id { |
867 | .unwrap_or(Ty::Unknown) | 805 | self.db.type_for_field(def_id, field.name.clone())? |
868 | } | 806 | } else { |
869 | Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, nr.as_name())?, | 807 | Ty::Unknown |
870 | _ => Ty::Unknown, | ||
871 | }; | 808 | }; |
872 | self.insert_type_vars(ty) | 809 | self.infer_expr(field.expr, &Expectation::has_type(field_ty))?; |
873 | } else { | 810 | } |
874 | Ty::Unknown | 811 | if let Some(expr) = spread { |
812 | self.infer_expr(*expr, &Expectation::has_type(ty.clone()))?; | ||
875 | } | 813 | } |
814 | ty | ||
815 | } | ||
816 | Expr::Field { expr, name } => { | ||
817 | let receiver_ty = self.infer_expr(*expr, &Expectation::none())?; | ||
818 | let ty = match receiver_ty { | ||
819 | Ty::Tuple(fields) => { | ||
820 | let i = name.to_string().parse::<usize>().ok(); | ||
821 | i.and_then(|i| fields.get(i).cloned()) | ||
822 | .unwrap_or(Ty::Unknown) | ||
823 | } | ||
824 | Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone())?, | ||
825 | _ => Ty::Unknown, | ||
826 | }; | ||
827 | self.insert_type_vars(ty) | ||
876 | } | 828 | } |
877 | ast::Expr::TryExpr(e) => { | 829 | Expr::Try { expr } => { |
878 | let _inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 830 | let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; |
879 | Ty::Unknown | 831 | Ty::Unknown |
880 | } | 832 | } |
881 | ast::Expr::CastExpr(e) => { | 833 | Expr::Cast { expr, type_ref } => { |
882 | let _inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 834 | let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; |
883 | let cast_ty = Ty::from_ast_opt( | 835 | let cast_ty = |
884 | self.db, | 836 | Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref)?; |
885 | &self.module, | ||
886 | self.impl_block.as_ref(), | ||
887 | e.type_ref(), | ||
888 | )?; | ||
889 | let cast_ty = self.insert_type_vars(cast_ty); | 837 | let cast_ty = self.insert_type_vars(cast_ty); |
890 | // TODO do the coercion... | 838 | // TODO check the cast... |
891 | cast_ty | 839 | cast_ty |
892 | } | 840 | } |
893 | ast::Expr::RefExpr(e) => { | 841 | Expr::Ref { expr, mutability } => { |
894 | // TODO pass the expectation down | 842 | // TODO pass the expectation down |
895 | let inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 843 | let inner_ty = self.infer_expr(*expr, &Expectation::none())?; |
896 | let m = Mutability::from_mutable(e.is_mut()); | ||
897 | // TODO reference coercions etc. | 844 | // TODO reference coercions etc. |
898 | Ty::Ref(Arc::new(inner_ty), m) | 845 | Ty::Ref(Arc::new(inner_ty), *mutability) |
899 | } | 846 | } |
900 | ast::Expr::PrefixExpr(e) => { | 847 | Expr::UnaryOp { expr, op } => { |
901 | let inner_ty = self.infer_expr_opt(e.expr(), &Expectation::none())?; | 848 | let inner_ty = self.infer_expr(*expr, &Expectation::none())?; |
902 | match e.op() { | 849 | match op { |
903 | Some(PrefixOp::Deref) => { | 850 | Some(UnaryOp::Deref) => { |
904 | match inner_ty { | 851 | match inner_ty { |
905 | // builtin deref: | 852 | // builtin deref: |
906 | Ty::Ref(ref_inner, _) => (*ref_inner).clone(), | 853 | Ty::Ref(ref_inner, _) => (*ref_inner).clone(), |
@@ -912,18 +859,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
912 | _ => Ty::Unknown, | 859 | _ => Ty::Unknown, |
913 | } | 860 | } |
914 | } | 861 | } |
915 | ast::Expr::RangeExpr(_e) => Ty::Unknown, | 862 | Expr::BinaryOp { lhs, rhs, op } => match op { |
916 | ast::Expr::BinExpr(e) => match e.op() { | ||
917 | Some(op) => { | 863 | Some(op) => { |
918 | let subtype_expectation = match op { | 864 | let subtype_expectation = match op { |
919 | BinOp::BooleanAnd | BinOp::BooleanOr => Expectation::has_type(Ty::Bool), | 865 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { |
866 | Expectation::has_type(Ty::Bool) | ||
867 | } | ||
920 | _ => Expectation::none(), | 868 | _ => Expectation::none(), |
921 | }; | 869 | }; |
922 | let (lhs, rhs) = e.sub_exprs(); | 870 | let _lhs_ty = self.infer_expr(*lhs, &subtype_expectation)?; |
923 | let _lhs_ty = self.infer_expr_opt(lhs, &subtype_expectation)?; | 871 | let _rhs_ty = self.infer_expr(*rhs, &subtype_expectation)?; |
924 | let _rhs_ty = self.infer_expr_opt(rhs, &subtype_expectation)?; | ||
925 | 872 | ||
926 | if is_boolean_operator(op) { | 873 | if is_boolean_operator(*op) { |
927 | Ty::Bool | 874 | Ty::Bool |
928 | } else { | 875 | } else { |
929 | Ty::Unknown | 876 | Ty::Unknown |
@@ -931,128 +878,93 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
931 | } | 878 | } |
932 | _ => Ty::Unknown, | 879 | _ => Ty::Unknown, |
933 | }, | 880 | }, |
934 | ast::Expr::Literal(_e) => Ty::Unknown, | ||
935 | }; | 881 | }; |
936 | // use a new type variable if we got Ty::Unknown here | 882 | // use a new type variable if we got Ty::Unknown here |
937 | let ty = self.insert_type_vars_shallow(ty); | 883 | let ty = self.insert_type_vars_shallow(ty); |
938 | self.unify(&ty, &expected.ty); | 884 | self.unify(&ty, &expected.ty); |
939 | self.write_ty(expr.syntax(), ty.clone()); | 885 | let ty = self.resolve_ty_as_possible(ty); |
886 | self.write_expr_ty(expr, ty.clone()); | ||
940 | Ok(ty) | 887 | Ok(ty) |
941 | } | 888 | } |
942 | 889 | ||
943 | fn infer_block_opt( | 890 | fn infer_block( |
944 | &mut self, | 891 | &mut self, |
945 | node: Option<ast::Block>, | 892 | statements: &[Statement], |
893 | tail: Option<ExprId>, | ||
946 | expected: &Expectation, | 894 | expected: &Expectation, |
947 | ) -> Cancelable<Ty> { | 895 | ) -> Cancelable<Ty> { |
948 | if let Some(b) = node { | 896 | for stmt in statements { |
949 | self.infer_block(b, expected) | ||
950 | } else { | ||
951 | Ok(Ty::Unknown) | ||
952 | } | ||
953 | } | ||
954 | |||
955 | fn infer_block(&mut self, node: ast::Block, expected: &Expectation) -> Cancelable<Ty> { | ||
956 | for stmt in node.statements() { | ||
957 | match stmt { | 897 | match stmt { |
958 | ast::Stmt::LetStmt(stmt) => { | 898 | Statement::Let { |
959 | let decl_ty = Ty::from_ast_opt( | 899 | pat, |
900 | type_ref, | ||
901 | initializer, | ||
902 | } => { | ||
903 | let decl_ty = Ty::from_hir_opt( | ||
960 | self.db, | 904 | self.db, |
961 | &self.module, | 905 | &self.module, |
962 | self.impl_block.as_ref(), | 906 | self.impl_block.as_ref(), |
963 | stmt.type_ref(), | 907 | type_ref.as_ref(), |
964 | )?; | 908 | )?; |
965 | let decl_ty = self.insert_type_vars(decl_ty); | 909 | let decl_ty = self.insert_type_vars(decl_ty); |
966 | let ty = if let Some(expr) = stmt.initializer() { | 910 | let ty = if let Some(expr) = initializer { |
967 | let expr_ty = self.infer_expr(expr, &Expectation::has_type(decl_ty))?; | 911 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty))?; |
968 | expr_ty | 912 | expr_ty |
969 | } else { | 913 | } else { |
970 | decl_ty | 914 | decl_ty |
971 | }; | 915 | }; |
972 | 916 | ||
973 | if let Some(pat) = stmt.pat() { | 917 | self.write_pat_ty(*pat, ty); |
974 | self.write_ty(pat.syntax(), ty); | ||
975 | }; | ||
976 | } | 918 | } |
977 | ast::Stmt::ExprStmt(expr_stmt) => { | 919 | Statement::Expr(expr) => { |
978 | self.infer_expr_opt(expr_stmt.expr(), &Expectation::none())?; | 920 | self.infer_expr(*expr, &Expectation::none())?; |
979 | } | 921 | } |
980 | } | 922 | } |
981 | } | 923 | } |
982 | let ty = if let Some(expr) = node.expr() { | 924 | let ty = if let Some(expr) = tail { |
983 | self.infer_expr(expr, expected)? | 925 | self.infer_expr(expr, expected)? |
984 | } else { | 926 | } else { |
985 | Ty::unit() | 927 | Ty::unit() |
986 | }; | 928 | }; |
987 | self.write_ty(node.syntax(), ty.clone()); | ||
988 | Ok(ty) | 929 | Ok(ty) |
989 | } | 930 | } |
990 | 931 | ||
991 | fn collect_fn_signature(&mut self, node: ast::FnDef) -> Cancelable<()> { | 932 | fn collect_fn_signature(&mut self, signature: &FnSignature) -> Cancelable<()> { |
992 | if let Some(param_list) = node.param_list() { | 933 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
993 | if let Some(self_param) = param_list.self_param() { | 934 | for (type_ref, pat) in signature.args().iter().zip(body.args()) { |
994 | let self_type = if let Some(type_ref) = self_param.type_ref() { | 935 | let ty = self.make_ty(type_ref)?; |
995 | let ty = self.make_ty(&TypeRef::from_ast(type_ref))?; | 936 | let ty = self.insert_type_vars(ty); |
996 | self.insert_type_vars(ty) | 937 | self.write_pat_ty(*pat, ty); |
997 | } else { | ||
998 | // TODO this should be handled by desugaring during HIR conversion | ||
999 | let ty = self.make_ty_opt(self.impl_block.as_ref().map(|i| i.target_type()))?; | ||
1000 | let ty = match self_param.flavor() { | ||
1001 | ast::SelfParamFlavor::Owned => ty, | ||
1002 | ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared), | ||
1003 | ast::SelfParamFlavor::MutRef => Ty::Ref(Arc::new(ty), Mutability::Mut), | ||
1004 | }; | ||
1005 | self.insert_type_vars(ty) | ||
1006 | }; | ||
1007 | if let Some(self_kw) = self_param.self_kw() { | ||
1008 | let self_param = LocalSyntaxPtr::new(self_kw.syntax()); | ||
1009 | self.self_param = Some(self_param); | ||
1010 | self.type_of.insert(self_param, self_type); | ||
1011 | } | ||
1012 | } | ||
1013 | for param in param_list.params() { | ||
1014 | let pat = if let Some(pat) = param.pat() { | ||
1015 | pat | ||
1016 | } else { | ||
1017 | continue; | ||
1018 | }; | ||
1019 | let ty = if let Some(type_ref) = param.type_ref() { | ||
1020 | let ty = self.make_ty(&TypeRef::from_ast(type_ref))?; | ||
1021 | self.insert_type_vars(ty) | ||
1022 | } else { | ||
1023 | // missing type annotation | ||
1024 | self.new_type_var() | ||
1025 | }; | ||
1026 | self.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty); | ||
1027 | } | ||
1028 | } | 938 | } |
1029 | 939 | self.return_ty = { | |
1030 | self.return_ty = if let Some(type_ref) = node.ret_type().and_then(|n| n.type_ref()) { | 940 | let ty = self.make_ty(signature.ret_type())?; |
1031 | let ty = self.make_ty(&TypeRef::from_ast(type_ref))?; | 941 | let ty = self.insert_type_vars(ty); |
1032 | self.insert_type_vars(ty) | 942 | ty |
1033 | } else { | ||
1034 | Ty::unit() | ||
1035 | }; | 943 | }; |
944 | Ok(()) | ||
945 | } | ||
1036 | 946 | ||
947 | fn infer_body(&mut self) -> Cancelable<()> { | ||
948 | self.infer_expr( | ||
949 | self.body.body_expr(), | ||
950 | &Expectation::has_type(self.return_ty.clone()), | ||
951 | )?; | ||
1037 | Ok(()) | 952 | Ok(()) |
1038 | } | 953 | } |
1039 | } | 954 | } |
1040 | 955 | ||
1041 | pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { | 956 | pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { |
1042 | let function = Function::new(def_id); // TODO: consts also need inference | 957 | let function = Function::new(def_id); // TODO: consts also need inference |
1043 | let scopes = function.scopes(db)?; | 958 | let body = function.body(db)?; |
959 | let scopes = db.fn_scopes(def_id)?; | ||
1044 | let module = function.module(db)?; | 960 | let module = function.module(db)?; |
1045 | let impl_block = function.impl_block(db)?; | 961 | let impl_block = function.impl_block(db)?; |
1046 | let mut ctx = InferenceContext::new(db, scopes, module, impl_block); | 962 | let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); |
1047 | |||
1048 | let syntax = function.syntax(db); | ||
1049 | let node = syntax.borrowed(); | ||
1050 | 963 | ||
1051 | ctx.collect_fn_signature(node)?; | 964 | let signature = function.signature(db); |
965 | ctx.collect_fn_signature(&signature)?; | ||
1052 | 966 | ||
1053 | if let Some(block) = node.body() { | 967 | ctx.infer_body()?; |
1054 | ctx.infer_block(block, &Expectation::has_type(ctx.return_ty.clone()))?; | ||
1055 | } | ||
1056 | 968 | ||
1057 | Ok(Arc::new(ctx.resolve_all())) | 969 | Ok(Arc::new(ctx.resolve_all())) |
1058 | } | 970 | } |