diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 90 |
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 | } |
703 | impl_froms!(VariantDef: Struct, EnumVariant); | 704 | impl_froms!(VariantDef: Struct, EnumVariant); |
704 | 705 | ||
705 | pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> { | 706 | impl 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 | |||
721 | pub(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); |