diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/expr.rs | 34 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/pat.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/utils.rs | 14 |
7 files changed, 60 insertions, 52 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 0e987240a..52ad4e5d1 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -534,14 +534,6 @@ impl VariantDef { | |||
534 | } | 534 | } |
535 | } | 535 | } |
536 | 536 | ||
537 | pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | ||
538 | match self { | ||
539 | VariantDef::Struct(it) => it.field(db, name), | ||
540 | VariantDef::Union(it) => it.field(db, name), | ||
541 | VariantDef::EnumVariant(it) => it.field(db, name), | ||
542 | } | ||
543 | } | ||
544 | |||
545 | pub fn module(self, db: &impl HirDatabase) -> Module { | 537 | pub fn module(self, db: &impl HirDatabase) -> Module { |
546 | match self { | 538 | match self { |
547 | VariantDef::Struct(it) => it.module(db), | 539 | VariantDef::Struct(it) => it.module(db), |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c85e38a0d..05f5bca57 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -229,12 +229,12 @@ impl SourceAnalyzer { | |||
229 | 229 | ||
230 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { | 230 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { |
231 | let expr_id = self.expr_id(&record_lit.clone().into())?; | 231 | let expr_id = self.expr_id(&record_lit.clone().into())?; |
232 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | 232 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into()) |
233 | } | 233 | } |
234 | 234 | ||
235 | pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { | 235 | pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { |
236 | let pat_id = self.pat_id(&record_pat.clone().into())?; | 236 | let pat_id = self.pat_id(&record_pat.clone().into())?; |
237 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) | 237 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id).map(|it| it.into()) |
238 | } | 238 | } |
239 | 239 | ||
240 | pub fn resolve_macro_call( | 240 | pub fn resolve_macro_call( |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 1eca4883d..59e4e5f36 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -28,7 +28,7 @@ use hir_def::{ | |||
28 | path::{known, Path}, | 28 | path::{known, Path}, |
29 | resolver::{HasResolver, Resolver, TypeNs}, | 29 | resolver::{HasResolver, Resolver, TypeNs}, |
30 | type_ref::{Mutability, TypeRef}, | 30 | type_ref::{Mutability, TypeRef}, |
31 | AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, | 31 | AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, |
32 | }; | 32 | }; |
33 | use hir_expand::{diagnostics::DiagnosticSink, name}; | 33 | use hir_expand::{diagnostics::DiagnosticSink, name}; |
34 | use ra_arena::map::ArenaMap; | 34 | use ra_arena::map::ArenaMap; |
@@ -41,7 +41,7 @@ use super::{ | |||
41 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, | 41 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, |
42 | TypeWalk, Uncertain, | 42 | TypeWalk, Uncertain, |
43 | }; | 43 | }; |
44 | use crate::{db::HirDatabase, ty::infer::diagnostics::InferenceDiagnostic, VariantDef}; | 44 | use crate::{db::HirDatabase, ty::infer::diagnostics::InferenceDiagnostic}; |
45 | 45 | ||
46 | macro_rules! ty_app { | 46 | macro_rules! ty_app { |
47 | ($ctor:pat, $param:pat) => { | 47 | ($ctor:pat, $param:pat) => { |
@@ -124,7 +124,7 @@ pub struct InferenceResult { | |||
124 | /// For each field in record literal, records the field it resolves to. | 124 | /// For each field in record literal, records the field it resolves to. |
125 | record_field_resolutions: FxHashMap<ExprId, StructFieldId>, | 125 | record_field_resolutions: FxHashMap<ExprId, StructFieldId>, |
126 | /// For each struct literal, records the variant it resolves to. | 126 | /// For each struct literal, records the variant it resolves to. |
127 | variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, | 127 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, |
128 | /// For each associated item record what it resolves to | 128 | /// For each associated item record what it resolves to |
129 | assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, | 129 | assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, |
130 | diagnostics: Vec<InferenceDiagnostic>, | 130 | diagnostics: Vec<InferenceDiagnostic>, |
@@ -143,10 +143,10 @@ impl InferenceResult { | |||
143 | pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructFieldId> { | 143 | pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructFieldId> { |
144 | self.record_field_resolutions.get(&expr).copied() | 144 | self.record_field_resolutions.get(&expr).copied() |
145 | } | 145 | } |
146 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> { | 146 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { |
147 | self.variant_resolutions.get(&id.into()).copied() | 147 | self.variant_resolutions.get(&id.into()).copied() |
148 | } | 148 | } |
149 | pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantDef> { | 149 | pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> { |
150 | self.variant_resolutions.get(&id.into()).copied() | 150 | self.variant_resolutions.get(&id.into()).copied() |
151 | } | 151 | } |
152 | pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<AssocItemId> { | 152 | pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<AssocItemId> { |
@@ -248,7 +248,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
248 | self.result.field_resolutions.insert(expr, field); | 248 | self.result.field_resolutions.insert(expr, field); |
249 | } | 249 | } |
250 | 250 | ||
251 | fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantDef) { | 251 | fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) { |
252 | self.result.variant_resolutions.insert(id, variant); | 252 | self.result.variant_resolutions.insert(id, variant); |
253 | } | 253 | } |
254 | 254 | ||
@@ -511,7 +511,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
511 | }) | 511 | }) |
512 | } | 512 | } |
513 | 513 | ||
514 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { | 514 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { |
515 | let path = match path { | 515 | let path = match path { |
516 | Some(path) => path, | 516 | Some(path) => path, |
517 | None => return (Ty::Unknown, None), | 517 | None => return (Ty::Unknown, None), |
@@ -524,13 +524,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
524 | let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); | 524 | let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); |
525 | let ty = self.db.ty(strukt.into()); | 525 | let ty = self.db.ty(strukt.into()); |
526 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 526 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
527 | (ty, Some(VariantDef::Struct(strukt.into()))) | 527 | (ty, Some(strukt.into())) |
528 | } | 528 | } |
529 | Some(TypeNs::EnumVariantId(var)) => { | 529 | Some(TypeNs::EnumVariantId(var)) => { |
530 | let substs = Ty::substs_from_path(self.db, resolver, path, var.into()); | 530 | let substs = Ty::substs_from_path(self.db, resolver, path, var.into()); |
531 | let ty = self.db.ty(var.parent.into()); | 531 | let ty = self.db.ty(var.parent.into()); |
532 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 532 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
533 | (ty, Some(VariantDef::EnumVariant(var.into()))) | 533 | (ty, Some(var.into())) |
534 | } | 534 | } |
535 | Some(_) | None => (Ty::Unknown, None), | 535 | Some(_) | None => (Ty::Unknown, None), |
536 | } | 536 | } |
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index d9ea6da42..f9ededa23 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs | |||
@@ -16,9 +16,9 @@ use hir_expand::name::{self, Name}; | |||
16 | use crate::{ | 16 | use crate::{ |
17 | db::HirDatabase, | 17 | db::HirDatabase, |
18 | ty::{ | 18 | ty::{ |
19 | autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, | 19 | autoderef, method_resolution, op, traits::InEnvironment, utils::variant_data, CallableDef, |
20 | Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 20 | InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, |
21 | TypeWalk, Uncertain, | 21 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, |
22 | }, | 22 | }, |
23 | }; | 23 | }; |
24 | 24 | ||
@@ -218,22 +218,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
218 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 218 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
219 | let field_types = | 219 | let field_types = |
220 | def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | 220 | def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default(); |
221 | let variant_data = def_id.map(|it| variant_data(self.db, it)); | ||
221 | for (field_idx, field) in fields.iter().enumerate() { | 222 | for (field_idx, field) in fields.iter().enumerate() { |
222 | let field_def = def_id.and_then(|it| match it.field(self.db, &field.name) { | 223 | let field_def = |
223 | Some(field) => Some(field), | 224 | variant_data.as_ref().and_then(|it| match it.field(&field.name) { |
224 | None => { | 225 | Some(local_id) => { |
225 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { | 226 | Some(StructFieldId { parent: def_id.unwrap(), local_id }) |
226 | expr: tgt_expr, | 227 | } |
227 | field: field_idx, | 228 | None => { |
228 | }); | 229 | self.push_diagnostic(InferenceDiagnostic::NoSuchField { |
229 | None | 230 | expr: tgt_expr, |
230 | } | 231 | field: field_idx, |
231 | }); | 232 | }); |
233 | None | ||
234 | } | ||
235 | }); | ||
232 | if let Some(field_def) = field_def { | 236 | if let Some(field_def) = field_def { |
233 | self.result.record_field_resolutions.insert(field.expr, field_def.into()); | 237 | self.result.record_field_resolutions.insert(field.expr, field_def); |
234 | } | 238 | } |
235 | let field_ty = field_def | 239 | let field_ty = field_def |
236 | .map_or(Ty::Unknown, |it| field_types[it.id].clone()) | 240 | .map_or(Ty::Unknown, |it| field_types[it.local_id].clone()) |
237 | .subst(&substs); | 241 | .subst(&substs); |
238 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); | 242 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
239 | } | 243 | } |
diff --git a/crates/ra_hir/src/ty/infer/pat.rs b/crates/ra_hir/src/ty/infer/pat.rs index 6dbf03eb2..a14774607 100644 --- a/crates/ra_hir/src/ty/infer/pat.rs +++ b/crates/ra_hir/src/ty/infer/pat.rs | |||
@@ -14,7 +14,7 @@ use test_utils::tested_by; | |||
14 | use super::{BindingMode, InferenceContext}; | 14 | use super::{BindingMode, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | db::HirDatabase, | 16 | db::HirDatabase, |
17 | ty::{Substs, Ty, TypeCtor, TypeWalk}, | 17 | ty::{utils::variant_data, Substs, Ty, TypeCtor, TypeWalk}, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 20 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
@@ -26,16 +26,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
26 | default_bm: BindingMode, | 26 | default_bm: BindingMode, |
27 | ) -> Ty { | 27 | ) -> Ty { |
28 | let (ty, def) = self.resolve_variant(path); | 28 | let (ty, def) = self.resolve_variant(path); |
29 | 29 | let var_data = def.map(|it| variant_data(self.db, it)); | |
30 | self.unify(&ty, expected); | 30 | self.unify(&ty, expected); |
31 | 31 | ||
32 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 32 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
33 | 33 | ||
34 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | 34 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); |
35 | |||
35 | for (i, &subpat) in subpats.iter().enumerate() { | 36 | for (i, &subpat) in subpats.iter().enumerate() { |
36 | let expected_ty = def | 37 | let expected_ty = var_data |
37 | .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) | 38 | .as_ref() |
38 | .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) | 39 | .and_then(|d| d.field(&Name::new_tuple_field(i))) |
40 | .map_or(Ty::Unknown, |field| field_tys[field].clone()) | ||
39 | .subst(&substs); | 41 | .subst(&substs); |
40 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 42 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
41 | self.infer_pat(subpat, &expected_ty, default_bm); | 43 | self.infer_pat(subpat, &expected_ty, default_bm); |
@@ -53,6 +55,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
53 | id: PatId, | 55 | id: PatId, |
54 | ) -> Ty { | 56 | ) -> Ty { |
55 | let (ty, def) = self.resolve_variant(path); | 57 | let (ty, def) = self.resolve_variant(path); |
58 | let var_data = def.map(|it| variant_data(self.db, it)); | ||
56 | if let Some(variant) = def { | 59 | if let Some(variant) = def { |
57 | self.write_variant_resolution(id.into(), variant); | 60 | self.write_variant_resolution(id.into(), variant); |
58 | } | 61 | } |
@@ -63,10 +66,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
63 | 66 | ||
64 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); | 67 | let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); |
65 | for subpat in subpats { | 68 | for subpat in subpats { |
66 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); | 69 | let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); |
67 | let expected_ty = matching_field | 70 | let expected_ty = |
68 | .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) | 71 | matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs); |
69 | .subst(&substs); | ||
70 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 72 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
71 | self.infer_pat(subpat.pat, &expected_ty, default_bm); | 73 | self.infer_pat(subpat.pat, &expected_ty, default_bm); |
72 | } | 74 | } |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 1c0f71adc..d33b50794 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -28,7 +28,7 @@ use crate::{ | |||
28 | db::HirDatabase, | 28 | db::HirDatabase, |
29 | ty::{ | 29 | ty::{ |
30 | primitive::{FloatTy, IntTy}, | 30 | primitive::{FloatTy, IntTy}, |
31 | utils::{all_super_traits, associated_type_by_name_including_super_traits}, | 31 | utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data}, |
32 | }, | 32 | }, |
33 | util::make_mut_slice, | 33 | util::make_mut_slice, |
34 | Adt, Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait, | 34 | Adt, Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait, |
@@ -514,13 +514,11 @@ pub(crate) fn field_types_query( | |||
514 | db: &impl HirDatabase, | 514 | db: &impl HirDatabase, |
515 | variant_id: VariantId, | 515 | variant_id: VariantId, |
516 | ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { | 516 | ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { |
517 | let (resolver, var_data) = match variant_id { | 517 | let var_data = variant_data(db, variant_id); |
518 | VariantId::StructId(it) => (it.resolver(db), db.struct_data(it).variant_data.clone()), | 518 | let resolver = match variant_id { |
519 | VariantId::UnionId(it) => (it.resolver(db), db.union_data(it).variant_data.clone()), | 519 | VariantId::StructId(it) => it.resolver(db), |
520 | VariantId::EnumVariantId(it) => ( | 520 | VariantId::UnionId(it) => it.resolver(db), |
521 | it.parent.resolver(db), | 521 | VariantId::EnumVariantId(it) => it.parent.resolver(db), |
522 | db.enum_data(it.parent).variants[it.local_id].variant_data.clone(), | ||
523 | ), | ||
524 | }; | 522 | }; |
525 | let mut res = ArenaMap::default(); | 523 | let mut res = ArenaMap::default(); |
526 | for (field_id, field_data) in var_data.fields().iter() { | 524 | for (field_id, field_data) in var_data.fields().iter() { |
diff --git a/crates/ra_hir/src/ty/utils.rs b/crates/ra_hir/src/ty/utils.rs index 80ffceb4b..f82e6ac9b 100644 --- a/crates/ra_hir/src/ty/utils.rs +++ b/crates/ra_hir/src/ty/utils.rs | |||
@@ -1,11 +1,13 @@ | |||
1 | //! Helper functions for working with def, which don't need to be a separate | 1 | //! Helper functions for working with def, which don't need to be a separate |
2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). | 2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). |
3 | use std::sync::Arc; | ||
3 | 4 | ||
4 | use hir_def::{ | 5 | use hir_def::{ |
6 | adt::VariantData, | ||
5 | db::DefDatabase, | 7 | db::DefDatabase, |
6 | resolver::{HasResolver, TypeNs}, | 8 | resolver::{HasResolver, TypeNs}, |
7 | type_ref::TypeRef, | 9 | type_ref::TypeRef, |
8 | TraitId, TypeAliasId, | 10 | TraitId, TypeAliasId, VariantId, |
9 | }; | 11 | }; |
10 | use hir_expand::name::{self, Name}; | 12 | use hir_expand::name::{self, Name}; |
11 | 13 | ||
@@ -61,3 +63,13 @@ pub(super) fn associated_type_by_name_including_super_traits( | |||
61 | .into_iter() | 63 | .into_iter() |
62 | .find_map(|t| db.trait_data(t).associated_type_by_name(name)) | 64 | .find_map(|t| db.trait_data(t).associated_type_by_name(name)) |
63 | } | 65 | } |
66 | |||
67 | pub(super) fn variant_data(db: &impl DefDatabase, var: VariantId) -> Arc<VariantData> { | ||
68 | match var { | ||
69 | VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), | ||
70 | VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), | ||
71 | VariantId::EnumVariantId(it) => { | ||
72 | db.enum_data(it.parent).variants[it.local_id].variant_data.clone() | ||
73 | } | ||
74 | } | ||
75 | } | ||