diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/expr/validation.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 19 |
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 && ¶ms[0] == expr_ty { | 124 | if params.len() == 2 && ¶ms[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)] | ||
111 | pub 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)] |
111 | pub struct InferenceResult { | 118 | pub 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 | ||
125 | impl InferenceResult { | 133 | impl 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 | ||