aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty.rs120
1 files changed, 62 insertions, 58 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index d11f80cff..45a01679c 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -522,6 +522,8 @@ struct InferenceContext<'a, D: HirDatabase> {
522 impl_block: Option<ImplBlock>, 522 impl_block: Option<ImplBlock>,
523 var_unification_table: InPlaceUnificationTable<TypeVarId>, 523 var_unification_table: InPlaceUnificationTable<TypeVarId>,
524 type_of: FxHashMap<LocalSyntaxPtr, Ty>, 524 type_of: FxHashMap<LocalSyntaxPtr, Ty>,
525 /// The return type of the function being inferred.
526 return_ty: Ty,
525} 527}
526 528
527impl<'a, D: HirDatabase> InferenceContext<'a, D> { 529impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -534,7 +536,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
534 InferenceContext { 536 InferenceContext {
535 type_of: FxHashMap::default(), 537 type_of: FxHashMap::default(),
536 var_unification_table: InPlaceUnificationTable::new(), 538 var_unification_table: InPlaceUnificationTable::new(),
537 self_param: None, // set during parameter typing 539 self_param: None, // set during parameter typing
540 return_ty: Ty::Unknown, // set in collect_fn_signature
538 db, 541 db,
539 scopes, 542 scopes,
540 module, 543 module,
@@ -555,6 +558,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
555 self.type_of.insert(LocalSyntaxPtr::new(node), ty); 558 self.type_of.insert(LocalSyntaxPtr::new(node), ty);
556 } 559 }
557 560
561 fn make_ty(&self, type_ref: &TypeRef) -> Cancelable<Ty> {
562 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref)
563 }
564
565 fn make_ty_opt(&self, type_ref: Option<&TypeRef>) -> Cancelable<Ty> {
566 Ty::from_hir_opt(self.db, &self.module, self.impl_block.as_ref(), type_ref)
567 }
568
558 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 569 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
559 match (ty1, ty2) { 570 match (ty1, ty2) {
560 (Ty::Unknown, ..) => true, 571 (Ty::Unknown, ..) => true,
@@ -952,78 +963,71 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
952 self.write_ty(node.syntax(), ty.clone()); 963 self.write_ty(node.syntax(), ty.clone());
953 Ok(ty) 964 Ok(ty)
954 } 965 }
955}
956
957pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> {
958 let function = Function::new(def_id); // TODO: consts also need inference
959 let scopes = function.scopes(db);
960 let module = function.module(db)?;
961 let impl_block = function.impl_block(db)?;
962 let mut ctx = InferenceContext::new(db, scopes, module, impl_block);
963 966
964 let syntax = function.syntax(db); 967 fn collect_fn_signature(&mut self, node: ast::FnDef) -> Cancelable<()> {
965 let node = syntax.borrowed(); 968 if let Some(param_list) = node.param_list() {
966 969 if let Some(self_param) = param_list.self_param() {
967 if let Some(param_list) = node.param_list() { 970 let self_type = if let Some(type_ref) = self_param.type_ref() {
968 if let Some(self_param) = param_list.self_param() { 971 let ty = self.make_ty(&TypeRef::from_ast(type_ref))?;
969 let self_type = if let Some(impl_block) = &ctx.impl_block { 972 self.insert_type_vars(ty)
970 if let Some(type_ref) = self_param.type_ref() {
971 let ty = Ty::from_ast(db, &ctx.module, ctx.impl_block.as_ref(), type_ref)?;
972 ctx.insert_type_vars(ty)
973 } else { 973 } else {
974 // TODO this should be handled by desugaring during HIR conversion 974 // TODO this should be handled by desugaring during HIR conversion
975 let ty = Ty::from_hir( 975 let ty = self.make_ty_opt(self.impl_block.as_ref().map(|i| i.target()))?;
976 db,
977 &ctx.module,
978 ctx.impl_block.as_ref(),
979 impl_block.target(),
980 )?;
981 let ty = match self_param.flavor() { 976 let ty = match self_param.flavor() {
982 ast::SelfParamFlavor::Owned => ty, 977 ast::SelfParamFlavor::Owned => ty,
983 ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared), 978 ast::SelfParamFlavor::Ref => Ty::Ref(Arc::new(ty), Mutability::Shared),
984 ast::SelfParamFlavor::MutRef => Ty::Ref(Arc::new(ty), Mutability::Mut), 979 ast::SelfParamFlavor::MutRef => Ty::Ref(Arc::new(ty), Mutability::Mut),
985 }; 980 };
986 ctx.insert_type_vars(ty) 981 self.insert_type_vars(ty)
982 };
983 if let Some(self_kw) = self_param.self_kw() {
984 let self_param = LocalSyntaxPtr::new(self_kw.syntax());
985 self.self_param = Some(self_param);
986 self.type_of.insert(self_param, self_type);
987 } 987 }
988 } else { 988 }
989 log::debug!( 989 for param in param_list.params() {
990 "No impl block found, but self param for function {:?}", 990 let pat = if let Some(pat) = param.pat() {
991 def_id 991 pat
992 ); 992 } else {
993 ctx.new_type_var() 993 continue;
994 }; 994 };
995 if let Some(self_kw) = self_param.self_kw() { 995 let ty = if let Some(type_ref) = param.type_ref() {
996 let self_param = LocalSyntaxPtr::new(self_kw.syntax()); 996 let ty = self.make_ty(&TypeRef::from_ast(type_ref))?;
997 ctx.self_param = Some(self_param); 997 self.insert_type_vars(ty)
998 ctx.type_of.insert(self_param, self_type); 998 } else {
999 // missing type annotation
1000 self.new_type_var()
1001 };
1002 self.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
999 } 1003 }
1000 } 1004 }
1001 for param in param_list.params() { 1005
1002 let pat = if let Some(pat) = param.pat() { 1006 self.return_ty = if let Some(type_ref) = node.ret_type().and_then(|n| n.type_ref()) {
1003 pat 1007 let ty = self.make_ty(&TypeRef::from_ast(type_ref))?;
1004 } else { 1008 self.insert_type_vars(ty)
1005 continue; 1009 } else {
1006 }; 1010 Ty::unit()
1007 let ty = if let Some(type_ref) = param.type_ref() { 1011 };
1008 let ty = Ty::from_ast(db, &ctx.module, ctx.impl_block.as_ref(), type_ref)?; 1012
1009 ctx.insert_type_vars(ty) 1013 Ok(())
1010 } else {
1011 // missing type annotation
1012 ctx.new_type_var()
1013 };
1014 ctx.type_of.insert(LocalSyntaxPtr::new(pat.syntax()), ty);
1015 }
1016 } 1014 }
1015}
1017 1016
1018 let ret_ty = if let Some(type_ref) = node.ret_type().and_then(|n| n.type_ref()) { 1017pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> {
1019 let ty = Ty::from_ast(db, &ctx.module, ctx.impl_block.as_ref(), type_ref)?; 1018 let function = Function::new(def_id); // TODO: consts also need inference
1020 ctx.insert_type_vars(ty) 1019 let scopes = function.scopes(db);
1021 } else { 1020 let module = function.module(db)?;
1022 Ty::unit() 1021 let impl_block = function.impl_block(db)?;
1023 }; 1022 let mut ctx = InferenceContext::new(db, scopes, module, impl_block);
1023
1024 let syntax = function.syntax(db);
1025 let node = syntax.borrowed();
1026
1027 ctx.collect_fn_signature(node)?;
1024 1028
1025 if let Some(block) = node.body() { 1029 if let Some(block) = node.body() {
1026 ctx.infer_block(block, &Expectation::has_type(ret_ty))?; 1030 ctx.infer_block(block, &Expectation::has_type(ctx.return_ty.clone()))?;
1027 } 1031 }
1028 1032
1029 Ok(Arc::new(ctx.resolve_all())) 1033 Ok(Arc::new(ctx.resolve_all()))