diff options
author | Sergey Parilin <[email protected]> | 2019-04-02 15:55:14 +0100 |
---|---|---|
committer | Sergey Parilin <[email protected]> | 2019-04-02 15:55:14 +0100 |
commit | b74449e9952846a8ea66c3507e52c24348d6dbc9 (patch) | |
tree | 00bb1101334b0bf1b189a2e6451cb28e0af959a1 /crates/ra_hir/src/ty/infer.rs | |
parent | 9b73f809596e955216dde24fcf921d6985a1a767 (diff) | |
parent | 849d7428aa6b733d452b2ebc55ec322d96345f49 (diff) |
Merge remote-tracking branch 'upstream/master' into issue961_profiling
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index cff7e7481..573115321 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -36,7 +36,9 @@ use crate::{ | |||
36 | path::{GenericArgs, GenericArg}, | 36 | path::{GenericArgs, GenericArg}, |
37 | adt::VariantDef, | 37 | adt::VariantDef, |
38 | resolve::{Resolver, Resolution}, | 38 | resolve::{Resolver, Resolution}, |
39 | nameres::Namespace | 39 | nameres::Namespace, |
40 | ty::infer::diagnostics::InferenceDiagnostic, | ||
41 | diagnostics::DiagnosticSink, | ||
40 | }; | 42 | }; |
41 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; | 43 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; |
42 | 44 | ||
@@ -96,6 +98,7 @@ pub struct InferenceResult { | |||
96 | field_resolutions: FxHashMap<ExprId, StructField>, | 98 | field_resolutions: FxHashMap<ExprId, StructField>, |
97 | /// For each associated item record what it resolves to | 99 | /// For each associated item record what it resolves to |
98 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, | 100 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, |
101 | diagnostics: Vec<InferenceDiagnostic>, | ||
99 | pub(super) type_of_expr: ArenaMap<ExprId, Ty>, | 102 | pub(super) type_of_expr: ArenaMap<ExprId, Ty>, |
100 | pub(super) type_of_pat: ArenaMap<PatId, Ty>, | 103 | pub(super) type_of_pat: ArenaMap<PatId, Ty>, |
101 | } | 104 | } |
@@ -113,6 +116,14 @@ impl InferenceResult { | |||
113 | pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> { | 116 | pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> { |
114 | self.assoc_resolutions.get(&id.into()).map(|it| *it) | 117 | self.assoc_resolutions.get(&id.into()).map(|it| *it) |
115 | } | 118 | } |
119 | pub(crate) fn add_diagnostics( | ||
120 | &self, | ||
121 | db: &impl HirDatabase, | ||
122 | owner: Function, | ||
123 | sink: &mut DiagnosticSink, | ||
124 | ) { | ||
125 | self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) | ||
126 | } | ||
116 | } | 127 | } |
117 | 128 | ||
118 | impl Index<ExprId> for InferenceResult { | 129 | impl Index<ExprId> for InferenceResult { |
@@ -143,6 +154,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
143 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, | 154 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, |
144 | type_of_expr: ArenaMap<ExprId, Ty>, | 155 | type_of_expr: ArenaMap<ExprId, Ty>, |
145 | type_of_pat: ArenaMap<PatId, Ty>, | 156 | type_of_pat: ArenaMap<PatId, Ty>, |
157 | diagnostics: Vec<InferenceDiagnostic>, | ||
146 | /// The return type of the function being inferred. | 158 | /// The return type of the function being inferred. |
147 | return_ty: Ty, | 159 | return_ty: Ty, |
148 | } | 160 | } |
@@ -155,6 +167,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
155 | assoc_resolutions: FxHashMap::default(), | 167 | assoc_resolutions: FxHashMap::default(), |
156 | type_of_expr: ArenaMap::default(), | 168 | type_of_expr: ArenaMap::default(), |
157 | type_of_pat: ArenaMap::default(), | 169 | type_of_pat: ArenaMap::default(), |
170 | diagnostics: Vec::default(), | ||
158 | var_unification_table: InPlaceUnificationTable::new(), | 171 | var_unification_table: InPlaceUnificationTable::new(), |
159 | return_ty: Ty::Unknown, // set in collect_fn_signature | 172 | return_ty: Ty::Unknown, // set in collect_fn_signature |
160 | db, | 173 | db, |
@@ -181,6 +194,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
181 | assoc_resolutions: self.assoc_resolutions, | 194 | assoc_resolutions: self.assoc_resolutions, |
182 | type_of_expr: expr_types, | 195 | type_of_expr: expr_types, |
183 | type_of_pat: pat_types, | 196 | type_of_pat: pat_types, |
197 | diagnostics: self.diagnostics, | ||
184 | } | 198 | } |
185 | } | 199 | } |
186 | 200 | ||
@@ -807,7 +821,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
807 | } | 821 | } |
808 | Expr::MethodCall { receiver, args, method_name, generic_args } => { | 822 | Expr::MethodCall { receiver, args, method_name, generic_args } => { |
809 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); | 823 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); |
810 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); | 824 | let resolved = |
825 | receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver); | ||
811 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | 826 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { |
812 | Some((ty, func)) => { | 827 | Some((ty, func)) => { |
813 | self.write_method_resolution(tgt_expr, func); | 828 | self.write_method_resolution(tgt_expr, func); |
@@ -915,9 +930,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
915 | Expr::StructLit { path, fields, spread } => { | 930 | Expr::StructLit { path, fields, spread } => { |
916 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | 931 | let (ty, def_id) = self.resolve_variant(path.as_ref()); |
917 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 932 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
918 | for field in fields { | 933 | for (field_idx, field) in fields.into_iter().enumerate() { |
919 | let field_ty = def_id | 934 | let field_ty = def_id |
920 | .and_then(|it| it.field(self.db, &field.name)) | 935 | .and_then(|it| match it.field(self.db, &field.name) { |
936 | Some(field) => Some(field), | ||
937 | None => { | ||
938 | self.diagnostics.push(InferenceDiagnostic::NoSuchField { | ||
939 | expr: tgt_expr, | ||
940 | field: field_idx, | ||
941 | }); | ||
942 | None | ||
943 | } | ||
944 | }) | ||
921 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 945 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
922 | .subst(&substs); | 946 | .subst(&substs); |
923 | self.infer_expr(field.expr, &Expectation::has_type(field_ty)); | 947 | self.infer_expr(field.expr, &Expectation::has_type(field_ty)); |
@@ -1244,3 +1268,29 @@ impl Expectation { | |||
1244 | Expectation { ty: Ty::Unknown } | 1268 | Expectation { ty: Ty::Unknown } |
1245 | } | 1269 | } |
1246 | } | 1270 | } |
1271 | |||
1272 | mod diagnostics { | ||
1273 | use crate::{expr::ExprId, diagnostics::{DiagnosticSink, NoSuchField}, HirDatabase, Function}; | ||
1274 | |||
1275 | #[derive(Debug, PartialEq, Eq, Clone)] | ||
1276 | pub(super) enum InferenceDiagnostic { | ||
1277 | NoSuchField { expr: ExprId, field: usize }, | ||
1278 | } | ||
1279 | |||
1280 | impl InferenceDiagnostic { | ||
1281 | pub(super) fn add_to( | ||
1282 | &self, | ||
1283 | db: &impl HirDatabase, | ||
1284 | owner: Function, | ||
1285 | sink: &mut DiagnosticSink, | ||
1286 | ) { | ||
1287 | match self { | ||
1288 | InferenceDiagnostic::NoSuchField { expr, field } => { | ||
1289 | let (file, _) = owner.source(db); | ||
1290 | let field = owner.body_source_map(db).field_syntax(*expr, *field); | ||
1291 | sink.push(NoSuchField { file, field }) | ||
1292 | } | ||
1293 | } | ||
1294 | } | ||
1295 | } | ||
1296 | } | ||