aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs90
1 files changed, 38 insertions, 52 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index c7f77e7a3..c57e222dd 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -38,6 +38,7 @@ use crate::{
38 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, 38 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat},
39 generics::GenericParams, 39 generics::GenericParams,
40 path::GenericArg, 40 path::GenericArg,
41 adt::VariantData,
41}; 42};
42 43
43/// The ID of a type variable. 44/// The ID of a type variable.
@@ -702,19 +703,30 @@ pub enum VariantDef {
702} 703}
703impl_froms!(VariantDef: Struct, EnumVariant); 704impl_froms!(VariantDef: Struct, EnumVariant);
704 705
705pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> { 706impl VariantDef {
706 let (variant_data, generics, module) = match def { 707 pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
707 VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)), 708 match self {
708 VariantDef::EnumVariant(var) => ( 709 VariantDef::Struct(it) => it.field(db, name),
709 var.variant_data(db), 710 VariantDef::EnumVariant(it) => it.field(db, name),
710 var.parent_enum(db).generic_params(db), 711 }
711 var.module(db), 712 }
712 ), 713 pub(crate) fn variant_data(self, db: &impl HirDatabase) -> Arc<VariantData> {
714 match self {
715 VariantDef::Struct(it) => it.variant_data(db),
716 VariantDef::EnumVariant(it) => it.variant_data(db),
717 }
718 }
719}
720
721pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
722 let parent_def = field.parent_def(db);
723 let (generics, module) = match parent_def {
724 VariantDef::Struct(it) => (it.generic_params(db), it.module(db)),
725 VariantDef::EnumVariant(it) => (it.parent_enum(db).generic_params(db), it.module(db)),
713 }; 726 };
714 // We can't have an impl block ere, right? 727 let var_data = parent_def.variant_data(db);
715 // let impl_block = def_id.impl_block(db); 728 let type_ref = &var_data.fields().unwrap()[field.id].type_ref;
716 let type_ref = variant_data.get_field_type_ref(&field)?; 729 Ty::from_hir(db, &module, None, &generics, type_ref)
717 Some(Ty::from_hir(db, &module, None, &generics, &type_ref))
718} 730}
719 731
720/// The result of type inference: A mapping from expressions and patterns to types. 732/// The result of type inference: A mapping from expressions and patterns to types.
@@ -1122,39 +1134,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1122 } 1134 }
1123 } 1135 }
1124 1136
1125 fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
1126 let (ty, def) = self.resolve_variant(path);
1127 match def? {
1128 VariantDef::Struct(s) => {
1129 let fields = s.fields(self.db);
1130 Some((ty, fields))
1131 }
1132 VariantDef::EnumVariant(var) => {
1133 let fields = var.fields(self.db);
1134 Some((ty, fields))
1135 }
1136 }
1137 }
1138
1139 fn infer_tuple_struct_pat( 1137 fn infer_tuple_struct_pat(
1140 &mut self, 1138 &mut self,
1141 path: Option<&Path>, 1139 path: Option<&Path>,
1142 subpats: &[PatId], 1140 subpats: &[PatId],
1143 expected: &Ty, 1141 expected: &Ty,
1144 ) -> Ty { 1142 ) -> Ty {
1145 let (ty, fields) = self 1143 let (ty, def) = self.resolve_variant(path);
1146 .resolve_fields(path)
1147 .unwrap_or((Ty::Unknown, Vec::new()));
1148 1144
1149 self.unify(&ty, expected); 1145 self.unify(&ty, expected);
1150 1146
1151 let substs = ty.substs().unwrap_or_else(Substs::empty); 1147 let substs = ty.substs().unwrap_or_else(Substs::empty);
1152 1148
1153 for (i, &subpat) in subpats.iter().enumerate() { 1149 for (i, &subpat) in subpats.iter().enumerate() {
1154 let expected_ty = fields 1150 let expected_ty = def
1155 .get(i) 1151 .and_then(|d| d.field(self.db, &Name::tuple_field_name(i)))
1156 .and_then(|field| field.ty(self.db)) 1152 .map_or(Ty::Unknown, |field| field.ty(self.db))
1157 .unwrap_or(Ty::Unknown)
1158 .subst(&substs); 1153 .subst(&substs);
1159 self.infer_pat(subpat, &expected_ty); 1154 self.infer_pat(subpat, &expected_ty);
1160 } 1155 }
@@ -1163,19 +1158,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1163 } 1158 }
1164 1159
1165 fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty { 1160 fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty {
1166 let (ty, fields) = self 1161 let (ty, def) = self.resolve_variant(path);
1167 .resolve_fields(path)
1168 .unwrap_or((Ty::Unknown, Vec::new()));
1169 1162
1170 self.unify(&ty, expected); 1163 self.unify(&ty, expected);
1171 1164
1172 let substs = ty.substs().unwrap_or_else(Substs::empty); 1165 let substs = ty.substs().unwrap_or_else(Substs::empty);
1173 1166
1174 for subpat in subpats { 1167 for subpat in subpats {
1175 let matching_field = fields.iter().find(|field| field.name() == &subpat.name); 1168 let matching_field = def.and_then(|it| it.field(self.db, &subpat.name));
1176 let expected_ty = matching_field 1169 let expected_ty = matching_field
1177 .and_then(|field| field.ty(self.db)) 1170 .map_or(Ty::Unknown, |field| field.ty(self.db))
1178 .unwrap_or(Ty::Unknown)
1179 .subst(&substs); 1171 .subst(&substs);
1180 self.infer_pat(subpat.pat, &expected_ty); 1172 self.infer_pat(subpat.pat, &expected_ty);
1181 } 1173 }
@@ -1420,14 +1412,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1420 let (ty, def_id) = self.resolve_variant(path.as_ref()); 1412 let (ty, def_id) = self.resolve_variant(path.as_ref());
1421 let substs = ty.substs().unwrap_or_else(Substs::empty); 1413 let substs = ty.substs().unwrap_or_else(Substs::empty);
1422 for field in fields { 1414 for field in fields {
1423 let field_ty = if let Some(def_id) = def_id { 1415 let field_ty = def_id
1424 self.db 1416 .and_then(|it| it.field(self.db, &field.name))
1425 .type_for_field(def_id.into(), field.name.clone()) 1417 .map_or(Ty::Unknown, |field| field.ty(self.db))
1426 .unwrap_or(Ty::Unknown) 1418 .subst(&substs);
1427 .subst(&substs)
1428 } else {
1429 Ty::Unknown
1430 };
1431 self.infer_expr(field.expr, &Expectation::has_type(field_ty)); 1419 self.infer_expr(field.expr, &Expectation::has_type(field_ty));
1432 } 1420 }
1433 if let Some(expr) = spread { 1421 if let Some(expr) = spread {
@@ -1440,7 +1428,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1440 let ty = receiver_ty 1428 let ty = receiver_ty
1441 .autoderef(self.db) 1429 .autoderef(self.db)
1442 .find_map(|derefed_ty| match derefed_ty { 1430 .find_map(|derefed_ty| match derefed_ty {
1443 // this is more complicated than necessary because type_for_field is cancelable
1444 Ty::Tuple(fields) => { 1431 Ty::Tuple(fields) => {
1445 let i = name.to_string().parse::<usize>().ok(); 1432 let i = name.to_string().parse::<usize>().ok();
1446 i.and_then(|i| fields.get(i).cloned()) 1433 i.and_then(|i| fields.get(i).cloned())
@@ -1449,10 +1436,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1449 def_id: AdtDef::Struct(s), 1436 def_id: AdtDef::Struct(s),
1450 ref substs, 1437 ref substs,
1451 .. 1438 ..
1452 } => self 1439 } => s
1453 .db 1440 .field(self.db, name)
1454 .type_for_field(s.into(), name.clone()) 1441 .map(|field| field.ty(self.db).subst(substs)),
1455 .map(|ty| ty.subst(substs)),
1456 _ => None, 1442 _ => None,
1457 }) 1443 })
1458 .unwrap_or(Ty::Unknown); 1444 .unwrap_or(Ty::Unknown);