diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index cca59538a..d94e8154b 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -37,8 +37,8 @@ use crate::{ | |||
37 | code_model::{ModuleDef::Trait, TypeAlias}, | 37 | code_model::{ModuleDef::Trait, TypeAlias}, |
38 | diagnostics::DiagnosticSink, | 38 | diagnostics::DiagnosticSink, |
39 | expr::{ | 39 | expr::{ |
40 | self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, FieldPat, Literal, Pat, | 40 | self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, Literal, Pat, PatId, |
41 | PatId, Statement, UnaryOp, | 41 | RecordFieldPat, Statement, UnaryOp, |
42 | }, | 42 | }, |
43 | generics::{GenericParams, HasGenericParams}, | 43 | generics::{GenericParams, HasGenericParams}, |
44 | name, | 44 | name, |
@@ -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, |
@@ -705,10 +716,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
705 | ty | 716 | ty |
706 | } | 717 | } |
707 | 718 | ||
708 | fn infer_struct_pat( | 719 | fn infer_record_pat( |
709 | &mut self, | 720 | &mut self, |
710 | path: Option<&Path>, | 721 | path: Option<&Path>, |
711 | subpats: &[FieldPat], | 722 | subpats: &[RecordFieldPat], |
712 | expected: &Ty, | 723 | expected: &Ty, |
713 | default_bm: BindingMode, | 724 | default_bm: BindingMode, |
714 | id: PatId, | 725 | id: PatId, |
@@ -800,7 +811,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
800 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) | 811 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) |
801 | } | 812 | } |
802 | Pat::Struct { path: ref p, args: ref fields } => { | 813 | Pat::Struct { path: ref p, args: ref fields } => { |
803 | self.infer_struct_pat(p.as_ref(), fields, expected, default_bm, pat) | 814 | self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) |
804 | } | 815 | } |
805 | Pat::Path(path) => { | 816 | Pat::Path(path) => { |
806 | // FIXME use correct resolver for the surrounding expression | 817 | // FIXME use correct resolver for the surrounding expression |
@@ -1103,7 +1114,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1103 | } | 1114 | } |
1104 | Ty::simple(TypeCtor::Never) | 1115 | Ty::simple(TypeCtor::Never) |
1105 | } | 1116 | } |
1106 | Expr::StructLit { path, fields, spread } => { | 1117 | Expr::RecordLit { path, fields, spread } => { |
1107 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 1118 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
1108 | if let Some(variant) = def_id { | 1119 | if let Some(variant) = def_id { |
1109 | self.write_variant_resolution(tgt_expr.into(), variant); | 1120 | self.write_variant_resolution(tgt_expr.into(), variant); |
@@ -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 | ||