aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/expr/validation.rs14
-rw-r--r--crates/ra_hir/src/ty.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs19
3 files changed, 27 insertions, 8 deletions
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index f5e641557..0e7b08c54 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -102,14 +102,16 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
102 } 102 }
103 103
104 fn validate_results_in_tail_expr(&mut self, id: ExprId, db: &impl HirDatabase) { 104 fn validate_results_in_tail_expr(&mut self, id: ExprId, db: &impl HirDatabase) {
105 let expr_ty = &self.infer[id]; 105 let mismatch = match self.infer.type_mismatch_for_expr(id) {
106 let func_ty = self.func.ty(db); 106 Some(m) => m,
107 let func_sig = func_ty.callable_sig(db).unwrap(); 107 None => return,
108 let ret = func_sig.ret(); 108 };
109 let ret = match ret { 109
110 let ret = match &mismatch.expected {
110 Ty::Apply(t) => t, 111 Ty::Apply(t) => t,
111 _ => return, 112 _ => return,
112 }; 113 };
114
113 let ret_enum = match ret.ctor { 115 let ret_enum = match ret.ctor {
114 TypeCtor::Adt(AdtDef::Enum(e)) => e, 116 TypeCtor::Adt(AdtDef::Enum(e)) => e,
115 _ => return, 117 _ => return,
@@ -119,7 +121,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
119 return; 121 return;
120 } 122 }
121 let params = &ret.parameters; 123 let params = &ret.parameters;
122 if params.len() == 2 && &params[0] == expr_ty { 124 if params.len() == 2 && &params[0] == &mismatch.actual {
123 let source_map = self.func.body_source_map(db); 125 let source_map = self.func.body_source_map(db);
124 let file_id = self.func.source(db).file_id; 126 let file_id = self.func.source(db).file_id;
125 let parse = db.parse(file_id.original_file(db)); 127 let parse = db.parse(file_id.original_file(db));
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 0efd94cef..b54c80318 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -516,7 +516,7 @@ impl Ty {
516 } 516 }
517 } 517 }
518 518
519 pub fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> { 519 fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
520 match self { 520 match self {
521 Ty::Apply(a_ty) => match a_ty.ctor { 521 Ty::Apply(a_ty) => match a_ty.ctor {
522 TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)), 522 TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)),
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index b33de5687..d94e8154b 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -106,6 +106,13 @@ impl Default for BindingMode {
106 } 106 }
107} 107}
108 108
109/// A mismatch between an expected and an inferred type.
110#[derive(Clone, PartialEq, Eq, Debug, Hash)]
111pub struct TypeMismatch {
112 pub expected: Ty,
113 pub actual: Ty,
114}
115
109/// The result of type inference: A mapping from expressions and patterns to types. 116/// The result of type inference: A mapping from expressions and patterns to types.
110#[derive(Clone, PartialEq, Eq, Debug, Default)] 117#[derive(Clone, PartialEq, Eq, Debug, Default)]
111pub struct InferenceResult { 118pub struct InferenceResult {
@@ -120,6 +127,7 @@ pub struct InferenceResult {
120 diagnostics: Vec<InferenceDiagnostic>, 127 diagnostics: Vec<InferenceDiagnostic>,
121 pub(super) type_of_expr: ArenaMap<ExprId, Ty>, 128 pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
122 pub(super) type_of_pat: ArenaMap<PatId, Ty>, 129 pub(super) type_of_pat: ArenaMap<PatId, Ty>,
130 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
123} 131}
124 132
125impl InferenceResult { 133impl InferenceResult {
@@ -141,6 +149,9 @@ impl InferenceResult {
141 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> { 149 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> {
142 self.assoc_resolutions.get(&id.into()).copied() 150 self.assoc_resolutions.get(&id.into()).copied()
143 } 151 }
152 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
153 self.type_mismatches.get(expr)
154 }
144 pub(crate) fn add_diagnostics( 155 pub(crate) fn add_diagnostics(
145 &self, 156 &self,
146 db: &impl HirDatabase, 157 db: &impl HirDatabase,
@@ -1345,9 +1356,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1345 }; 1356 };
1346 // use a new type variable if we got Ty::Unknown here 1357 // use a new type variable if we got Ty::Unknown here
1347 let ty = self.insert_type_vars_shallow(ty); 1358 let ty = self.insert_type_vars_shallow(ty);
1348 self.unify(&ty, &expected.ty); 1359 let could_unify = self.unify(&ty, &expected.ty);
1349 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 1360 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
1350 self.write_expr_ty(tgt_expr, ty.clone()); 1361 self.write_expr_ty(tgt_expr, ty.clone());
1362 if !could_unify {
1363 self.result.type_mismatches.insert(
1364 tgt_expr,
1365 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
1366 );
1367 }
1351 ty 1368 ty
1352 } 1369 }
1353 1370