aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model.rs8
-rw-r--r--crates/ra_hir/src/source_binder.rs4
-rw-r--r--crates/ra_hir/src/ty/infer.rs18
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs34
-rw-r--r--crates/ra_hir/src/ty/infer/pat.rs20
-rw-r--r--crates/ra_hir/src/ty/lower.rs14
-rw-r--r--crates/ra_hir/src/ty/utils.rs14
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};
33use hir_expand::{diagnostics::DiagnosticSink, name}; 33use hir_expand::{diagnostics::DiagnosticSink, name};
34use ra_arena::map::ArenaMap; 34use 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};
44use crate::{db::HirDatabase, ty::infer::diagnostics::InferenceDiagnostic, VariantDef}; 44use crate::{db::HirDatabase, ty::infer::diagnostics::InferenceDiagnostic};
45 45
46macro_rules! ty_app { 46macro_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};
16use crate::{ 16use 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;
14use super::{BindingMode, InferenceContext}; 14use super::{BindingMode, InferenceContext};
15use crate::{ 15use 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
20impl<'a, D: HirDatabase> InferenceContext<'a, D> { 20impl<'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`).
3use std::sync::Arc;
3 4
4use hir_def::{ 5use 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};
10use hir_expand::name::{self, Name}; 12use 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
67pub(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}