diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 1d2d1b906..3608daae4 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -683,9 +683,9 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { | |||
683 | 683 | ||
684 | pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { | 684 | pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { |
685 | let def = def_id.resolve(db); | 685 | let def = def_id.resolve(db); |
686 | let variant_data = match def { | 686 | let (variant_data, generics) = match def { |
687 | Def::Struct(s) => s.variant_data(db), | 687 | Def::Struct(s) => (s.variant_data(db), s.generics(db)), |
688 | Def::EnumVariant(ev) => ev.variant_data(db), | 688 | Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generics(db)), |
689 | // TODO: unions | 689 | // TODO: unions |
690 | _ => panic!( | 690 | _ => panic!( |
691 | "trying to get type for field in non-struct/variant {:?}", | 691 | "trying to get type for field in non-struct/variant {:?}", |
@@ -694,7 +694,6 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) | |||
694 | }; | 694 | }; |
695 | let module = def_id.module(db); | 695 | let module = def_id.module(db); |
696 | let impl_block = def_id.impl_block(db); | 696 | let impl_block = def_id.impl_block(db); |
697 | let generics = db.generics(def_id); | ||
698 | let type_ref = variant_data.get_field_type_ref(&field)?; | 697 | let type_ref = variant_data.get_field_type_ref(&field)?; |
699 | Some(Ty::from_hir( | 698 | Some(Ty::from_hir( |
700 | db, | 699 | db, |
@@ -893,6 +892,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
893 | ty | 892 | ty |
894 | } | 893 | } |
895 | 894 | ||
895 | fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool { | ||
896 | substs1 | ||
897 | .0 | ||
898 | .iter() | ||
899 | .zip(substs2.0.iter()) | ||
900 | .all(|(t1, t2)| self.unify(t1, t2)) | ||
901 | } | ||
902 | |||
896 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 903 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
897 | // try to resolve type vars first | 904 | // try to resolve type vars first |
898 | let ty1 = self.resolve_ty_shallow(ty1); | 905 | let ty1 = self.resolve_ty_shallow(ty1); |
@@ -913,12 +920,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
913 | (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, | 920 | (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, |
914 | ( | 921 | ( |
915 | Ty::Adt { | 922 | Ty::Adt { |
916 | def_id: def_id1, .. | 923 | def_id: def_id1, |
924 | substs: substs1, | ||
925 | .. | ||
917 | }, | 926 | }, |
918 | Ty::Adt { | 927 | Ty::Adt { |
919 | def_id: def_id2, .. | 928 | def_id: def_id2, |
929 | substs: substs2, | ||
930 | .. | ||
920 | }, | 931 | }, |
921 | ) if def_id1 == def_id2 => true, | 932 | ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2), |
922 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), | 933 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), |
923 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), | 934 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), |
924 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), | 935 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), |
@@ -1088,49 +1099,65 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1088 | } | 1099 | } |
1089 | } | 1100 | } |
1090 | 1101 | ||
1091 | fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { | 1102 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { |
1092 | let def_id = self.module.resolve_path(self.db, path?).take_types()?; | 1103 | let (ty, def_id) = self.resolve_variant(path); |
1104 | let def_id = def_id?; | ||
1093 | let def = def_id.resolve(self.db); | 1105 | let def = def_id.resolve(self.db); |
1094 | 1106 | ||
1095 | match def { | 1107 | match def { |
1096 | Def::Struct(s) => { | 1108 | Def::Struct(s) => { |
1097 | let fields = s.fields(self.db); | 1109 | let fields = s.fields(self.db); |
1098 | Some((type_for_struct(self.db, s), fields)) | 1110 | Some((ty, fields)) |
1099 | } | 1111 | } |
1100 | Def::EnumVariant(ev) => { | 1112 | Def::EnumVariant(ev) => { |
1101 | let fields = ev.fields(self.db); | 1113 | let fields = ev.fields(self.db); |
1102 | Some((type_for_enum_variant(self.db, ev), fields)) | 1114 | Some((ty, fields)) |
1103 | } | 1115 | } |
1104 | _ => None, | 1116 | _ => None, |
1105 | } | 1117 | } |
1106 | } | 1118 | } |
1107 | 1119 | ||
1108 | fn infer_tuple_struct_pat(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty { | 1120 | fn infer_tuple_struct_pat( |
1121 | &mut self, | ||
1122 | path: Option<&Path>, | ||
1123 | subpats: &[PatId], | ||
1124 | expected: &Ty, | ||
1125 | ) -> Ty { | ||
1109 | let (ty, fields) = self | 1126 | let (ty, fields) = self |
1110 | .resolve_fields(path) | 1127 | .resolve_fields(path) |
1111 | .unwrap_or((Ty::Unknown, Vec::new())); | 1128 | .unwrap_or((Ty::Unknown, Vec::new())); |
1112 | 1129 | ||
1130 | self.unify(&ty, expected); | ||
1131 | |||
1132 | let substs = ty.substs().expect("adt should have substs"); | ||
1133 | |||
1113 | for (i, &subpat) in subpats.iter().enumerate() { | 1134 | for (i, &subpat) in subpats.iter().enumerate() { |
1114 | let expected_ty = fields | 1135 | let expected_ty = fields |
1115 | .get(i) | 1136 | .get(i) |
1116 | .and_then(|field| field.ty(self.db)) | 1137 | .and_then(|field| field.ty(self.db)) |
1117 | .unwrap_or(Ty::Unknown); | 1138 | .unwrap_or(Ty::Unknown) |
1139 | .subst(&substs); | ||
1118 | self.infer_pat(subpat, &expected_ty); | 1140 | self.infer_pat(subpat, &expected_ty); |
1119 | } | 1141 | } |
1120 | 1142 | ||
1121 | ty | 1143 | ty |
1122 | } | 1144 | } |
1123 | 1145 | ||
1124 | fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty { | 1146 | fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty { |
1125 | let (ty, fields) = self | 1147 | let (ty, fields) = self |
1126 | .resolve_fields(path) | 1148 | .resolve_fields(path) |
1127 | .unwrap_or((Ty::Unknown, Vec::new())); | 1149 | .unwrap_or((Ty::Unknown, Vec::new())); |
1128 | 1150 | ||
1151 | self.unify(&ty, expected); | ||
1152 | |||
1153 | let substs = ty.substs().expect("adt should have substs"); | ||
1154 | |||
1129 | for subpat in subpats { | 1155 | for subpat in subpats { |
1130 | let matching_field = fields.iter().find(|field| field.name() == &subpat.name); | 1156 | let matching_field = fields.iter().find(|field| field.name() == &subpat.name); |
1131 | let expected_ty = matching_field | 1157 | let expected_ty = matching_field |
1132 | .and_then(|field| field.ty(self.db)) | 1158 | .and_then(|field| field.ty(self.db)) |
1133 | .unwrap_or(Ty::Unknown); | 1159 | .unwrap_or(Ty::Unknown) |
1160 | .subst(&substs); | ||
1134 | self.infer_pat(subpat.pat, &expected_ty); | 1161 | self.infer_pat(subpat.pat, &expected_ty); |
1135 | } | 1162 | } |
1136 | 1163 | ||
@@ -1175,11 +1202,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1175 | Pat::TupleStruct { | 1202 | Pat::TupleStruct { |
1176 | path: ref p, | 1203 | path: ref p, |
1177 | args: ref subpats, | 1204 | args: ref subpats, |
1178 | } => self.infer_tuple_struct_pat(p.as_ref(), subpats), | 1205 | } => self.infer_tuple_struct_pat(p.as_ref(), subpats, expected), |
1179 | Pat::Struct { | 1206 | Pat::Struct { |
1180 | path: ref p, | 1207 | path: ref p, |
1181 | args: ref fields, | 1208 | args: ref fields, |
1182 | } => self.infer_struct_pat(p.as_ref(), fields), | 1209 | } => self.infer_struct_pat(p.as_ref(), fields, expected), |
1183 | Pat::Path(path) => self | 1210 | Pat::Path(path) => self |
1184 | .module | 1211 | .module |
1185 | .resolve_path(self.db, &path) | 1212 | .resolve_path(self.db, &path) |