aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model_api.rs2
-rw-r--r--crates/ra_hir/src/db.rs6
-rw-r--r--crates/ra_hir/src/lib.rs9
-rw-r--r--crates/ra_hir/src/ty.rs128
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs37
-rw-r--r--crates/ra_hir/src/ty/tests.rs6
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs15
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs2
-rw-r--r--crates/ra_ide_api/src/hover.rs2
9 files changed, 88 insertions, 119 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index d0c455d0a..0cf45944f 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -318,7 +318,7 @@ impl Function {
318 db.fn_signature(self.def_id) 318 db.fn_signature(self.def_id)
319 } 319 }
320 320
321 pub fn infer(&self, db: &impl HirDatabase) -> Cancelable<Arc<InferenceResult>> { 321 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
322 db.infer(self.def_id) 322 db.infer(self.def_id)
323 } 323 }
324} 324}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 4a2b0b3dc..0a0994f5f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; 3use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
4use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable}; 4use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase};
5 5
6use crate::{ 6use crate::{
7 DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId, 7 DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
@@ -52,7 +52,7 @@ pub trait HirDatabase: SyntaxDatabase
52 use fn crate::adt::EnumVariantData::enum_variant_data_query; 52 use fn crate::adt::EnumVariantData::enum_variant_data_query;
53 } 53 }
54 54
55 fn infer(def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 55 fn infer(def_id: DefId) -> Arc<InferenceResult> {
56 type InferQuery; 56 type InferQuery;
57 use fn crate::ty::infer; 57 use fn crate::ty::infer;
58 } 58 }
@@ -102,7 +102,7 @@ pub trait HirDatabase: SyntaxDatabase
102 use fn crate::impl_block::impls_in_module; 102 use fn crate::impl_block::impls_in_module;
103 } 103 }
104 104
105 fn impls_in_crate(krate: Crate) -> Cancelable<Arc<CrateImplBlocks>> { 105 fn impls_in_crate(krate: Crate) -> Arc<CrateImplBlocks> {
106 type ImplsInCrateQuery; 106 type ImplsInCrateQuery;
107 use fn crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query; 107 use fn crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query;
108 } 108 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 45dda4f7f..ef7d049ee 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -5,15 +5,6 @@
5//! to a particular crate instance. That is, it has cfg flags and features 5//! to a particular crate instance. That is, it has cfg flags and features
6//! applied. So, the relation between syntax and HIR is many-to-one. 6//! applied. So, the relation between syntax and HIR is many-to-one.
7 7
8macro_rules! ctry {
9 ($expr:expr) => {
10 match $expr {
11 None => return Ok(None),
12 Some(it) => it,
13 }
14 };
15}
16
17pub mod db; 8pub mod db;
18#[cfg(test)] 9#[cfg(test)]
19mod mock; 10mod mock;
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 37fc8643a..dbbbce795 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -30,8 +30,6 @@ use ra_arena::map::ArenaMap;
30use join_to_string::join; 30use join_to_string::join;
31use rustc_hash::FxHashMap; 31use rustc_hash::FxHashMap;
32 32
33use ra_db::Cancelable;
34
35use crate::{ 33use crate::{
36 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock, 34 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock,
37 FnSignature, FnScopes, 35 FnSignature, FnScopes,
@@ -41,14 +39,6 @@ use crate::{
41 expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement}, 39 expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement},
42}; 40};
43 41
44fn transpose<T>(x: Cancelable<Option<T>>) -> Option<Cancelable<T>> {
45 match x {
46 Ok(Some(t)) => Some(Ok(t)),
47 Ok(None) => None,
48 Err(e) => Some(Err(e)),
49 }
50}
51
52/// The ID of a type variable. 42/// The ID of a type variable.
53#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 43#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
54pub struct TypeVarId(u32); 44pub struct TypeVarId(u32);
@@ -836,36 +826,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
836 }) 826 })
837 } 827 }
838 828
839 fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Cancelable<Option<Ty>> { 829 fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Option<Ty> {
840 if path.is_ident() || path.is_self() { 830 if path.is_ident() || path.is_self() {
841 // resolve locally 831 // resolve locally
842 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); 832 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param);
843 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { 833 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) {
844 let ty = ctry!(self.type_of_pat.get(scope_entry.pat())); 834 let ty = self.type_of_pat.get(scope_entry.pat())?;
845 let ty = self.resolve_ty_as_possible(ty.clone()); 835 let ty = self.resolve_ty_as_possible(ty.clone());
846 return Ok(Some(ty)); 836 return Some(ty);
847 }; 837 };
848 }; 838 };
849 839
850 // resolve in module 840 // resolve in module
851 let resolved = ctry!(self.module.resolve_path(self.db, &path).take_values()); 841 let resolved = self.module.resolve_path(self.db, &path).take_values()?;
852 let ty = self.db.type_for_def(resolved); 842 let ty = self.db.type_for_def(resolved);
853 let ty = self.insert_type_vars(ty); 843 let ty = self.insert_type_vars(ty);
854 Ok(Some(ty)) 844 Some(ty)
855 } 845 }
856 846
857 fn resolve_variant(&self, path: Option<&Path>) -> Cancelable<(Ty, Option<DefId>)> { 847 fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) {
858 let path = if let Some(path) = path { 848 let path = if let Some(path) = path {
859 path 849 path
860 } else { 850 } else {
861 return Ok((Ty::Unknown, None)); 851 return (Ty::Unknown, None);
862 }; 852 };
863 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() { 853 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() {
864 def_id 854 def_id
865 } else { 855 } else {
866 return Ok((Ty::Unknown, None)); 856 return (Ty::Unknown, None);
867 }; 857 };
868 Ok(match def_id.resolve(self.db) { 858 match def_id.resolve(self.db) {
869 Def::Struct(s) => { 859 Def::Struct(s) => {
870 let ty = type_for_struct(self.db, s); 860 let ty = type_for_struct(self.db, s);
871 (ty, Some(def_id)) 861 (ty, Some(def_id))
@@ -875,10 +865,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
875 (ty, Some(def_id)) 865 (ty, Some(def_id))
876 } 866 }
877 _ => (Ty::Unknown, None), 867 _ => (Ty::Unknown, None),
878 }) 868 }
879 } 869 }
880 870
881 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Cancelable<Ty> { 871 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
882 let body = Arc::clone(&self.body); // avoid borrow checker problem 872 let body = Arc::clone(&self.body); // avoid borrow checker problem
883 let ty = match &body[expr] { 873 let ty = match &body[expr] {
884 Expr::Missing => Ty::Unknown, 874 Expr::Missing => Ty::Unknown,
@@ -888,11 +878,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
888 else_branch, 878 else_branch,
889 } => { 879 } => {
890 // if let is desugared to match, so this is always simple if 880 // if let is desugared to match, so this is always simple if
891 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; 881 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool));
892 let then_ty = self.infer_expr(*then_branch, expected)?; 882 let then_ty = self.infer_expr(*then_branch, expected);
893 match else_branch { 883 match else_branch {
894 Some(else_branch) => { 884 Some(else_branch) => {
895 self.infer_expr(*else_branch, expected)?; 885 self.infer_expr(*else_branch, expected);
896 } 886 }
897 None => { 887 None => {
898 // no else branch -> unit 888 // no else branch -> unit
@@ -901,31 +891,31 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
901 }; 891 };
902 then_ty 892 then_ty
903 } 893 }
904 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected)?, 894 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
905 Expr::Loop { body } => { 895 Expr::Loop { body } => {
906 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 896 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
907 // TODO handle break with value 897 // TODO handle break with value
908 Ty::Never 898 Ty::Never
909 } 899 }
910 Expr::While { condition, body } => { 900 Expr::While { condition, body } => {
911 // while let is desugared to a match loop, so this is always simple while 901 // while let is desugared to a match loop, so this is always simple while
912 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; 902 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool));
913 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 903 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
914 Ty::unit() 904 Ty::unit()
915 } 905 }
916 Expr::For { iterable, body, .. } => { 906 Expr::For { iterable, body, .. } => {
917 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 907 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none());
918 // TODO write type for pat 908 // TODO write type for pat
919 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 909 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
920 Ty::unit() 910 Ty::unit()
921 } 911 }
922 Expr::Lambda { body, .. } => { 912 Expr::Lambda { body, .. } => {
923 // TODO write types for args, infer lambda type etc. 913 // TODO write types for args, infer lambda type etc.
924 let _body_ty = self.infer_expr(*body, &Expectation::none())?; 914 let _body_ty = self.infer_expr(*body, &Expectation::none());
925 Ty::Unknown 915 Ty::Unknown
926 } 916 }
927 Expr::Call { callee, args } => { 917 Expr::Call { callee, args } => {
928 let callee_ty = self.infer_expr(*callee, &Expectation::none())?; 918 let callee_ty = self.infer_expr(*callee, &Expectation::none());
929 let (param_tys, ret_ty) = match &callee_ty { 919 let (param_tys, ret_ty) = match &callee_ty {
930 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), 920 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()),
931 _ => { 921 _ => {
@@ -938,7 +928,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
938 self.infer_expr( 928 self.infer_expr(
939 *arg, 929 *arg,
940 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), 930 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
941 )?; 931 );
942 } 932 }
943 ret_ty 933 ret_ty
944 } 934 }
@@ -947,8 +937,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
947 args, 937 args,
948 method_name, 938 method_name,
949 } => { 939 } => {
950 let receiver_ty = self.infer_expr(*receiver, &Expectation::none())?; 940 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
951 let resolved = receiver_ty.clone().lookup_method(self.db, method_name)?; 941 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
952 let method_ty = match resolved { 942 let method_ty = match resolved {
953 Some(def_id) => { 943 Some(def_id) => {
954 self.write_method_resolution(expr, def_id); 944 self.write_method_resolution(expr, def_id);
@@ -974,32 +964,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
974 self.infer_expr( 964 self.infer_expr(
975 *arg, 965 *arg,
976 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), 966 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
977 )?; 967 );
978 } 968 }
979 ret_ty 969 ret_ty
980 } 970 }
981 Expr::Match { expr, arms } => { 971 Expr::Match { expr, arms } => {
982 let _ty = self.infer_expr(*expr, &Expectation::none())?; 972 let _ty = self.infer_expr(*expr, &Expectation::none());
983 for arm in arms { 973 for arm in arms {
984 // TODO type the bindings in pats 974 // TODO type the bindings in pats
985 // TODO type the guard 975 // TODO type the guard
986 let _ty = self.infer_expr(arm.expr, &Expectation::none())?; 976 let _ty = self.infer_expr(arm.expr, &Expectation::none());
987 } 977 }
988 // TODO unify all the match arm types 978 // TODO unify all the match arm types
989 Ty::Unknown 979 Ty::Unknown
990 } 980 }
991 Expr::Path(p) => self.infer_path_expr(expr, p)?.unwrap_or(Ty::Unknown), 981 Expr::Path(p) => self.infer_path_expr(expr, p).unwrap_or(Ty::Unknown),
992 Expr::Continue => Ty::Never, 982 Expr::Continue => Ty::Never,
993 Expr::Break { expr } => { 983 Expr::Break { expr } => {
994 if let Some(expr) = expr { 984 if let Some(expr) = expr {
995 // TODO handle break with value 985 // TODO handle break with value
996 self.infer_expr(*expr, &Expectation::none())?; 986 self.infer_expr(*expr, &Expectation::none());
997 } 987 }
998 Ty::Never 988 Ty::Never
999 } 989 }
1000 Expr::Return { expr } => { 990 Expr::Return { expr } => {
1001 if let Some(expr) = expr { 991 if let Some(expr) = expr {
1002 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone()))?; 992 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone()));
1003 } 993 }
1004 Ty::Never 994 Ty::Never
1005 } 995 }
@@ -1008,7 +998,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1008 fields, 998 fields,
1009 spread, 999 spread,
1010 } => { 1000 } => {
1011 let (ty, def_id) = self.resolve_variant(path.as_ref())?; 1001 let (ty, def_id) = self.resolve_variant(path.as_ref());
1012 for field in fields { 1002 for field in fields {
1013 let field_ty = if let Some(def_id) = def_id { 1003 let field_ty = if let Some(def_id) = def_id {
1014 self.db 1004 self.db
@@ -1017,37 +1007,35 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1017 } else { 1007 } else {
1018 Ty::Unknown 1008 Ty::Unknown
1019 }; 1009 };
1020 self.infer_expr(field.expr, &Expectation::has_type(field_ty))?; 1010 self.infer_expr(field.expr, &Expectation::has_type(field_ty));
1021 } 1011 }
1022 if let Some(expr) = spread { 1012 if let Some(expr) = spread {
1023 self.infer_expr(*expr, &Expectation::has_type(ty.clone()))?; 1013 self.infer_expr(*expr, &Expectation::has_type(ty.clone()));
1024 } 1014 }
1025 ty 1015 ty
1026 } 1016 }
1027 Expr::Field { expr, name } => { 1017 Expr::Field { expr, name } => {
1028 let receiver_ty = self.infer_expr(*expr, &Expectation::none())?; 1018 let receiver_ty = self.infer_expr(*expr, &Expectation::none());
1029 let ty = receiver_ty 1019 let ty = receiver_ty
1030 .autoderef(self.db) 1020 .autoderef(self.db)
1031 .find_map(|derefed_ty| match derefed_ty { 1021 .find_map(|derefed_ty| match derefed_ty {
1032 // this is more complicated than necessary because type_for_field is cancelable 1022 // this is more complicated than necessary because type_for_field is cancelable
1033 Ty::Tuple(fields) => { 1023 Ty::Tuple(fields) => {
1034 let i = name.to_string().parse::<usize>().ok(); 1024 let i = name.to_string().parse::<usize>().ok();
1035 i.and_then(|i| fields.get(i).cloned()).map(Ok) 1025 i.and_then(|i| fields.get(i).cloned())
1036 }
1037 Ty::Adt { def_id, .. } => {
1038 transpose(Ok(self.db.type_for_field(def_id, name.clone())))
1039 } 1026 }
1027 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()),
1040 _ => None, 1028 _ => None,
1041 }) 1029 })
1042 .unwrap_or(Ok(Ty::Unknown))?; 1030 .unwrap_or(Ty::Unknown);
1043 self.insert_type_vars(ty) 1031 self.insert_type_vars(ty)
1044 } 1032 }
1045 Expr::Try { expr } => { 1033 Expr::Try { expr } => {
1046 let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1034 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1047 Ty::Unknown 1035 Ty::Unknown
1048 } 1036 }
1049 Expr::Cast { expr, type_ref } => { 1037 Expr::Cast { expr, type_ref } => {
1050 let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1038 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1051 let cast_ty = 1039 let cast_ty =
1052 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref); 1040 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref);
1053 let cast_ty = self.insert_type_vars(cast_ty); 1041 let cast_ty = self.insert_type_vars(cast_ty);
@@ -1056,12 +1044,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1056 } 1044 }
1057 Expr::Ref { expr, mutability } => { 1045 Expr::Ref { expr, mutability } => {
1058 // TODO pass the expectation down 1046 // TODO pass the expectation down
1059 let inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1047 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1060 // TODO reference coercions etc. 1048 // TODO reference coercions etc.
1061 Ty::Ref(Arc::new(inner_ty), *mutability) 1049 Ty::Ref(Arc::new(inner_ty), *mutability)
1062 } 1050 }
1063 Expr::UnaryOp { expr, op } => { 1051 Expr::UnaryOp { expr, op } => {
1064 let inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1052 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1065 match op { 1053 match op {
1066 Some(UnaryOp::Deref) => { 1054 Some(UnaryOp::Deref) => {
1067 if let Some(derefed_ty) = inner_ty.builtin_deref() { 1055 if let Some(derefed_ty) = inner_ty.builtin_deref() {
@@ -1082,11 +1070,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1082 } 1070 }
1083 _ => Expectation::none(), 1071 _ => Expectation::none(),
1084 }; 1072 };
1085 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation)?; 1073 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
1086 // TODO: find implementation of trait corresponding to operation 1074 // TODO: find implementation of trait corresponding to operation
1087 // symbol and resolve associated `Output` type 1075 // symbol and resolve associated `Output` type
1088 let rhs_expectation = binary_op_rhs_expectation(*op, lhs_ty); 1076 let rhs_expectation = binary_op_rhs_expectation(*op, lhs_ty);
1089 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation))?; 1077 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
1090 1078
1091 // TODO: similar as above, return ty is often associated trait type 1079 // TODO: similar as above, return ty is often associated trait type
1092 binary_op_return_ty(*op, rhs_ty) 1080 binary_op_return_ty(*op, rhs_ty)
@@ -1096,7 +1084,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1096 Expr::Tuple { exprs } => { 1084 Expr::Tuple { exprs } => {
1097 let mut ty_vec = Vec::with_capacity(exprs.len()); 1085 let mut ty_vec = Vec::with_capacity(exprs.len());
1098 for arg in exprs.iter() { 1086 for arg in exprs.iter() {
1099 ty_vec.push(self.infer_expr(*arg, &Expectation::none())?); 1087 ty_vec.push(self.infer_expr(*arg, &Expectation::none()));
1100 } 1088 }
1101 1089
1102 Ty::Tuple(Arc::from(ty_vec)) 1090 Ty::Tuple(Arc::from(ty_vec))
@@ -1121,7 +1109,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1121 self.unify(&ty, &expected.ty); 1109 self.unify(&ty, &expected.ty);
1122 let ty = self.resolve_ty_as_possible(ty); 1110 let ty = self.resolve_ty_as_possible(ty);
1123 self.write_expr_ty(expr, ty.clone()); 1111 self.write_expr_ty(expr, ty.clone());
1124 Ok(ty) 1112 ty
1125 } 1113 }
1126 1114
1127 fn infer_block( 1115 fn infer_block(
@@ -1129,7 +1117,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1129 statements: &[Statement], 1117 statements: &[Statement],
1130 tail: Option<ExprId>, 1118 tail: Option<ExprId>,
1131 expected: &Expectation, 1119 expected: &Expectation,
1132 ) -> Cancelable<Ty> { 1120 ) -> Ty {
1133 for stmt in statements { 1121 for stmt in statements {
1134 match stmt { 1122 match stmt {
1135 Statement::Let { 1123 Statement::Let {
@@ -1145,7 +1133,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1145 ); 1133 );
1146 let decl_ty = self.insert_type_vars(decl_ty); 1134 let decl_ty = self.insert_type_vars(decl_ty);
1147 let ty = if let Some(expr) = initializer { 1135 let ty = if let Some(expr) = initializer {
1148 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty))?; 1136 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
1149 expr_ty 1137 expr_ty
1150 } else { 1138 } else {
1151 decl_ty 1139 decl_ty
@@ -1154,19 +1142,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1154 self.write_pat_ty(*pat, ty); 1142 self.write_pat_ty(*pat, ty);
1155 } 1143 }
1156 Statement::Expr(expr) => { 1144 Statement::Expr(expr) => {
1157 self.infer_expr(*expr, &Expectation::none())?; 1145 self.infer_expr(*expr, &Expectation::none());
1158 } 1146 }
1159 } 1147 }
1160 } 1148 }
1161 let ty = if let Some(expr) = tail { 1149 let ty = if let Some(expr) = tail {
1162 self.infer_expr(expr, expected)? 1150 self.infer_expr(expr, expected)
1163 } else { 1151 } else {
1164 Ty::unit() 1152 Ty::unit()
1165 }; 1153 };
1166 Ok(ty) 1154 ty
1167 } 1155 }
1168 1156
1169 fn collect_fn_signature(&mut self, signature: &FnSignature) -> Cancelable<()> { 1157 fn collect_fn_signature(&mut self, signature: &FnSignature) {
1170 let body = Arc::clone(&self.body); // avoid borrow checker problem 1158 let body = Arc::clone(&self.body); // avoid borrow checker problem
1171 for (type_ref, pat) in signature.params().iter().zip(body.params()) { 1159 for (type_ref, pat) in signature.params().iter().zip(body.params()) {
1172 let ty = self.make_ty(type_ref); 1160 let ty = self.make_ty(type_ref);
@@ -1178,19 +1166,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1178 let ty = self.insert_type_vars(ty); 1166 let ty = self.insert_type_vars(ty);
1179 ty 1167 ty
1180 }; 1168 };
1181 Ok(())
1182 } 1169 }
1183 1170
1184 fn infer_body(&mut self) -> Cancelable<()> { 1171 fn infer_body(&mut self) {
1185 self.infer_expr( 1172 self.infer_expr(
1186 self.body.body_expr(), 1173 self.body.body_expr(),
1187 &Expectation::has_type(self.return_ty.clone()), 1174 &Expectation::has_type(self.return_ty.clone()),
1188 )?; 1175 );
1189 Ok(())
1190 } 1176 }
1191} 1177}
1192 1178
1193pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 1179pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> {
1194 db.check_canceled(); 1180 db.check_canceled();
1195 let function = Function::new(def_id); // TODO: consts also need inference 1181 let function = Function::new(def_id); // TODO: consts also need inference
1196 let body = function.body(db); 1182 let body = function.body(db);
@@ -1200,9 +1186,9 @@ pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceRe
1200 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); 1186 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
1201 1187
1202 let signature = function.signature(db); 1188 let signature = function.signature(db);
1203 ctx.collect_fn_signature(&signature)?; 1189 ctx.collect_fn_signature(&signature);
1204 1190
1205 ctx.infer_body()?; 1191 ctx.infer_body();
1206 1192
1207 Ok(Arc::new(ctx.resolve_all())) 1193 Arc::new(ctx.resolve_all())
1208} 1194}
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 0676a989d..b221bd142 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
6 6
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
9use ra_db::{Cancelable, SourceRootId}; 9use ra_db::SourceRootId;
10 10
11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; 11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}};
12use super::Ty; 12use super::Ty;
@@ -42,7 +42,7 @@ impl CrateImplBlocks {
42 &'a self, 42 &'a self,
43 db: &'a impl HirDatabase, 43 db: &'a impl HirDatabase,
44 ty: &Ty, 44 ty: &Ty,
45 ) -> impl Iterator<Item = Cancelable<ImplBlock>> + 'a { 45 ) -> impl Iterator<Item = ImplBlock> + 'a {
46 let fingerprint = TyFingerprint::for_impl(ty); 46 let fingerprint = TyFingerprint::for_impl(ty);
47 fingerprint 47 fingerprint
48 .and_then(|f| self.impls.get(&f)) 48 .and_then(|f| self.impls.get(&f))
@@ -50,11 +50,11 @@ impl CrateImplBlocks {
50 .flat_map(|i| i.iter()) 50 .flat_map(|i| i.iter())
51 .map(move |(module_id, impl_id)| { 51 .map(move |(module_id, impl_id)| {
52 let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id); 52 let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id);
53 Ok(ImplBlock::from_id(module_impl_blocks, *impl_id)) 53 ImplBlock::from_id(module_impl_blocks, *impl_id)
54 }) 54 })
55 } 55 }
56 56
57 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> { 57 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
58 let module_id = module.def_id.loc(db).module_id; 58 let module_id = module.def_id.loc(db).module_id;
59 let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id); 59 let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id);
60 60
@@ -76,16 +76,14 @@ impl CrateImplBlocks {
76 } 76 }
77 77
78 for child in module.children(db) { 78 for child in module.children(db) {
79 self.collect_recursive(db, child)?; 79 self.collect_recursive(db, child);
80 } 80 }
81
82 Ok(())
83 } 81 }
84 82
85 pub(crate) fn impls_in_crate_query( 83 pub(crate) fn impls_in_crate_query(
86 db: &impl HirDatabase, 84 db: &impl HirDatabase,
87 krate: Crate, 85 krate: Crate,
88 ) -> Cancelable<Arc<CrateImplBlocks>> { 86 ) -> Arc<CrateImplBlocks> {
89 let crate_graph = db.crate_graph(); 87 let crate_graph = db.crate_graph();
90 let file_id = crate_graph.crate_root(krate.crate_id); 88 let file_id = crate_graph.crate_root(krate.crate_id);
91 let source_root_id = db.file_source_root(file_id); 89 let source_root_id = db.file_source_root(file_id);
@@ -94,9 +92,9 @@ impl CrateImplBlocks {
94 impls: FxHashMap::default(), 92 impls: FxHashMap::default(),
95 }; 93 };
96 if let Some(module) = krate.root_module(db) { 94 if let Some(module) = krate.root_module(db) {
97 crate_impl_blocks.collect_recursive(db, module)?; 95 crate_impl_blocks.collect_recursive(db, module);
98 } 96 }
99 Ok(Arc::new(crate_impl_blocks)) 97 Arc::new(crate_impl_blocks)
100 } 98 }
101} 99}
102 100
@@ -111,13 +109,13 @@ impl Ty {
111 // TODO: cache this as a query? 109 // TODO: cache this as a query?
112 // - if so, what signature? (TyFingerprint, Name)? 110 // - if so, what signature? (TyFingerprint, Name)?
113 // - or maybe cache all names and def_ids of methods per fingerprint? 111 // - or maybe cache all names and def_ids of methods per fingerprint?
114 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<DefId>> { 112 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<DefId> {
115 self.iterate_methods(db, |f| { 113 self.iterate_methods(db, |f| {
116 let sig = f.signature(db); 114 let sig = f.signature(db);
117 if sig.name() == name && sig.has_self_param() { 115 if sig.name() == name && sig.has_self_param() {
118 Ok(Some(f.def_id())) 116 Some(f.def_id())
119 } else { 117 } else {
120 Ok(None) 118 None
121 } 119 }
122 }) 120 })
123 } 121 }
@@ -127,8 +125,8 @@ impl Ty {
127 pub fn iterate_methods<T>( 125 pub fn iterate_methods<T>(
128 self, 126 self,
129 db: &impl HirDatabase, 127 db: &impl HirDatabase,
130 mut callback: impl FnMut(Function) -> Cancelable<Option<T>>, 128 mut callback: impl FnMut(Function) -> Option<T>,
131 ) -> Cancelable<Option<T>> { 129 ) -> Option<T> {
132 // For method calls, rust first does any number of autoderef, and then one 130 // For method calls, rust first does any number of autoderef, and then one
133 // autoref (i.e. when the method takes &self or &mut self). We just ignore 131 // autoref (i.e. when the method takes &self or &mut self). We just ignore
134 // the autoref currently -- when we find a method matching the given name, 132 // the autoref currently -- when we find a method matching the given name,
@@ -143,15 +141,14 @@ impl Ty {
143 Some(krate) => krate, 141 Some(krate) => krate,
144 None => continue, 142 None => continue,
145 }; 143 };
146 let impls = db.impls_in_crate(krate)?; 144 let impls = db.impls_in_crate(krate);
147 145
148 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) { 146 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) {
149 let impl_block = impl_block?;
150 for item in impl_block.items() { 147 for item in impl_block.items() {
151 match item { 148 match item {
152 ImplItem::Method(f) => { 149 ImplItem::Method(f) => {
153 if let Some(result) = callback(f.clone())? { 150 if let Some(result) = callback(f.clone()) {
154 return Ok(Some(result)); 151 return Some(result);
155 } 152 }
156 } 153 }
157 _ => {} 154 _ => {}
@@ -159,6 +156,6 @@ impl Ty {
159 } 156 }
160 } 157 }
161 } 158 }
162 Ok(None) 159 None
163 } 160 }
164} 161}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index b44ac9987..929fee04c 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -321,7 +321,7 @@ fn infer(content: &str) -> String {
321 .filter_map(ast::FnDef::cast) 321 .filter_map(ast::FnDef::cast)
322 { 322 {
323 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap(); 323 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
324 let inference_result = func.infer(&db).unwrap(); 324 let inference_result = func.infer(&db);
325 let body_syntax_mapping = func.body_syntax_mapping(&db); 325 let body_syntax_mapping = func.body_syntax_mapping(&db);
326 let mut types = Vec::new(); 326 let mut types = Vec::new();
327 for (pat, ty) in inference_result.type_of_pat.iter() { 327 for (pat, ty) in inference_result.type_of_pat.iter() {
@@ -405,7 +405,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
405 let func = source_binder::function_from_position(&db, pos).unwrap(); 405 let func = source_binder::function_from_position(&db, pos).unwrap();
406 { 406 {
407 let events = db.log_executed(|| { 407 let events = db.log_executed(|| {
408 func.infer(&db).unwrap(); 408 func.infer(&db);
409 }); 409 });
410 assert!(format!("{:?}", events).contains("infer")) 410 assert!(format!("{:?}", events).contains("infer"))
411 } 411 }
@@ -424,7 +424,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
424 424
425 { 425 {
426 let events = db.log_executed(|| { 426 let events = db.log_executed(|| {
427 func.infer(&db).unwrap(); 427 func.infer(&db);
428 }); 428 });
429 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) 429 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
430 } 430 }
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 30a0a3924..31a2478d1 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -9,7 +9,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) -> Ca
9 (Some(function), Some(receiver)) => (function, receiver), 9 (Some(function), Some(receiver)) => (function, receiver),
10 _ => return Ok(()), 10 _ => return Ok(()),
11 }; 11 };
12 let infer_result = function.infer(ctx.db)?; 12 let infer_result = function.infer(ctx.db);
13 let syntax_mapping = function.body_syntax_mapping(ctx.db); 13 let syntax_mapping = function.body_syntax_mapping(ctx.db);
14 let expr = match syntax_mapping.node_expr(receiver) { 14 let expr = match syntax_mapping.node_expr(receiver) {
15 Some(expr) => expr, 15 Some(expr) => expr,
@@ -19,7 +19,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) -> Ca
19 if !ctx.is_call { 19 if !ctx.is_call {
20 complete_fields(acc, ctx, receiver_ty.clone()); 20 complete_fields(acc, ctx, receiver_ty.clone());
21 } 21 }
22 complete_methods(acc, ctx, receiver_ty)?; 22 complete_methods(acc, ctx, receiver_ty);
23 Ok(()) 23 Ok(())
24} 24}
25 25
@@ -55,11 +55,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
55 } 55 }
56} 56}
57 57
58fn complete_methods( 58fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
59 acc: &mut Completions,
60 ctx: &CompletionContext,
61 receiver: Ty,
62) -> Cancelable<()> {
63 receiver.iterate_methods(ctx.db, |func| { 59 receiver.iterate_methods(ctx.db, |func| {
64 let sig = func.signature(ctx.db); 60 let sig = func.signature(ctx.db);
65 if sig.has_self_param() { 61 if sig.has_self_param() {
@@ -68,9 +64,8 @@ fn complete_methods(
68 .kind(CompletionItemKind::Method) 64 .kind(CompletionItemKind::Method)
69 .add_to(acc); 65 .add_to(acc);
70 } 66 }
71 Ok(None::<()>) 67 None::<()>
72 })?; 68 });
73 Ok(())
74} 69}
75 70
76#[cfg(test)] 71#[cfg(test)]
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index cdd8e211d..e0f3deb0b 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -63,7 +63,7 @@ pub(crate) fn reference_definition(
63 .parent() 63 .parent()
64 .and_then(ast::MethodCallExpr::cast) 64 .and_then(ast::MethodCallExpr::cast)
65 { 65 {
66 let infer_result = function.infer(db)?; 66 let infer_result = function.infer(db);
67 let syntax_mapping = function.body_syntax_mapping(db); 67 let syntax_mapping = function.body_syntax_mapping(db);
68 let expr = ast::Expr::cast(method_call.syntax()).unwrap(); 68 let expr = ast::Expr::cast(method_call.syntax()).unwrap();
69 if let Some(def_id) = syntax_mapping 69 if let Some(def_id) = syntax_mapping
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 0e9c48421..6b5887bda 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -73,7 +73,7 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Cancelable<Option
73 frange.file_id, 73 frange.file_id,
74 parent_fn 74 parent_fn
75 )); 75 ));
76 let infer = function.infer(db)?; 76 let infer = function.infer(db);
77 let syntax_mapping = function.body_syntax_mapping(db); 77 let syntax_mapping = function.body_syntax_mapping(db);
78 if let Some(expr) = ast::Expr::cast(node).and_then(|e| syntax_mapping.node_expr(e)) { 78 if let Some(expr) = ast::Expr::cast(node).and_then(|e| syntax_mapping.node_expr(e)) {
79 Ok(Some(infer[expr].to_string())) 79 Ok(Some(infer[expr].to_string()))