aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-04-07 16:09:02 +0100
committerAleksey Kladov <[email protected]>2020-04-07 17:34:17 +0100
commit4c29214bba65d23e18875bd060325c489be5a8e4 (patch)
treecaf82fa6db2c2f7f9293dc556445cc8b0eb47f58 /crates/ra_hir/src
parent7819d99d6bc617ee8653e9dc2fa4d82072d6c594 (diff)
Move computation of missing fields into hir
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs31
-rw-r--r--crates/ra_hir/src/semantics.rs28
-rw-r--r--crates/ra_hir/src/source_analyzer.rs90
3 files changed, 98 insertions, 51 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index c6f3bdb8e..9baebf643 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1027,8 +1027,16 @@ impl Type {
1027 ty: Ty, 1027 ty: Ty,
1028 ) -> Option<Type> { 1028 ) -> Option<Type> {
1029 let krate = resolver.krate()?; 1029 let krate = resolver.krate()?;
1030 Some(Type::new_with_resolver_inner(db, krate, resolver, ty))
1031 }
1032 pub(crate) fn new_with_resolver_inner(
1033 db: &dyn HirDatabase,
1034 krate: CrateId,
1035 resolver: &Resolver,
1036 ty: Ty,
1037 ) -> Type {
1030 let environment = TraitEnvironment::lower(db, &resolver); 1038 let environment = TraitEnvironment::lower(db, &resolver);
1031 Some(Type { krate, ty: InEnvironment { value: ty, environment } }) 1039 Type { krate, ty: InEnvironment { value: ty, environment } }
1032 } 1040 }
1033 1041
1034 fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { 1042 fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type {
@@ -1152,27 +1160,6 @@ impl Type {
1152 res 1160 res
1153 } 1161 }
1154 1162
1155 pub fn variant_fields(
1156 &self,
1157 db: &dyn HirDatabase,
1158 def: VariantDef,
1159 ) -> Vec<(StructField, Type)> {
1160 // FIXME: check that ty and def match
1161 match &self.ty.value {
1162 Ty::Apply(a_ty) => {
1163 let field_types = db.field_types(def.into());
1164 def.fields(db)
1165 .into_iter()
1166 .map(|it| {
1167 let ty = field_types[it.id].clone().subst(&a_ty.parameters);
1168 (it, self.derived(ty))
1169 })
1170 .collect()
1171 }
1172 _ => Vec::new(),
1173 }
1174 }
1175
1176 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { 1163 pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
1177 // There should be no inference vars in types passed here 1164 // There should be no inference vars in types passed here
1178 // FIXME check that? 1165 // FIXME check that?
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 2ad231d36..2707e422d 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -23,7 +23,7 @@ use crate::{
23 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 23 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
24 source_analyzer::{resolve_hir_path, SourceAnalyzer}, 24 source_analyzer::{resolve_hir_path, SourceAnalyzer},
25 AssocItem, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, Name, 25 AssocItem, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, Name,
26 Origin, Path, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, 26 Origin, Path, ScopeDef, StructField, Trait, Type, TypeParam,
27}; 27};
28 28
29#[derive(Debug, Clone, PartialEq, Eq)] 29#[derive(Debug, Clone, PartialEq, Eq)]
@@ -187,14 +187,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
187 self.analyze(field.syntax()).resolve_record_field(self.db, field) 187 self.analyze(field.syntax()).resolve_record_field(self.db, field)
188 } 188 }
189 189
190 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> {
191 self.analyze(record_lit.syntax()).resolve_record_literal(self.db, record_lit)
192 }
193
194 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<VariantDef> {
195 self.analyze(record_pat.syntax()).resolve_record_pattern(record_pat)
196 }
197
198 pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { 190 pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> {
199 let sa = self.analyze(macro_call.syntax()); 191 let sa = self.analyze(macro_call.syntax());
200 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); 192 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call);
@@ -212,6 +204,24 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
212 // FIXME: use this instead? 204 // FIXME: use this instead?
213 // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>; 205 // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
214 206
207 pub fn record_literal_missing_fields(
208 &self,
209 literal: &ast::RecordLit,
210 ) -> Vec<(StructField, Type)> {
211 self.analyze(literal.syntax())
212 .record_literal_missing_fields(self.db, literal)
213 .unwrap_or_default()
214 }
215
216 pub fn record_pattern_missing_fields(
217 &self,
218 pattern: &ast::RecordPat,
219 ) -> Vec<(StructField, Type)> {
220 self.analyze(pattern.syntax())
221 .record_pattern_missing_fields(self.db, pattern)
222 .unwrap_or_default()
223 }
224
215 pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> { 225 pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
216 let src = self.find_file(src.syntax().clone()).with_value(src).cloned(); 226 let src = self.find_file(src.syntax().clone()).with_value(src).cloned();
217 T::to_def(self, src) 227 T::to_def(self, src)
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 815ca158c..45631f8fd 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -14,10 +14,13 @@ use hir_def::{
14 }, 14 },
15 expr::{ExprId, Pat, PatId}, 15 expr::{ExprId, Pat, PatId},
16 resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, 16 resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
17 AsMacroCall, DefWithBodyId, 17 AsMacroCall, DefWithBodyId, LocalStructFieldId, StructFieldId, VariantId,
18}; 18};
19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
20use hir_ty::InferenceResult; 20use hir_ty::{
21 expr::{record_literal_missing_fields, record_pattern_missing_fields},
22 InferenceResult, Substs, Ty,
23};
21use ra_syntax::{ 24use ra_syntax::{
22 ast::{self, AstNode}, 25 ast::{self, AstNode},
23 SyntaxNode, SyntaxNodePtr, TextUnit, 26 SyntaxNode, SyntaxNodePtr, TextUnit,
@@ -25,8 +28,10 @@ use ra_syntax::{
25 28
26use crate::{ 29use crate::{
27 db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Function, Local, MacroDef, 30 db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Function, Local, MacroDef,
28 ModPath, ModuleDef, Path, PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam, 31 ModPath, ModuleDef, Path, PathKind, Static, Struct, StructField, Trait, Type, TypeAlias,
32 TypeParam,
29}; 33};
34use ra_db::CrateId;
30 35
31/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 36/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
32/// original source files. It should not be used inside the HIR itself. 37/// original source files. It should not be used inside the HIR itself.
@@ -164,23 +169,6 @@ impl SourceAnalyzer {
164 Some((struct_field.into(), local)) 169 Some((struct_field.into(), local))
165 } 170 }
166 171
167 pub(crate) fn resolve_record_literal(
168 &self,
169 db: &dyn HirDatabase,
170 record_lit: &ast::RecordLit,
171 ) -> Option<crate::VariantDef> {
172 let expr_id = self.expr_id(db, &record_lit.clone().into())?;
173 self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into())
174 }
175
176 pub(crate) fn resolve_record_pattern(
177 &self,
178 record_pat: &ast::RecordPat,
179 ) -> Option<crate::VariantDef> {
180 let pat_id = self.pat_id(&record_pat.clone().into())?;
181 self.infer.as_ref()?.variant_resolution_for_pat(pat_id).map(|it| it.into())
182 }
183
184 pub(crate) fn resolve_macro_call( 172 pub(crate) fn resolve_macro_call(
185 &self, 173 &self,
186 db: &dyn HirDatabase, 174 db: &dyn HirDatabase,
@@ -231,6 +219,68 @@ impl SourceAnalyzer {
231 resolve_hir_path(db, &self.resolver, &hir_path) 219 resolve_hir_path(db, &self.resolver, &hir_path)
232 } 220 }
233 221
222 pub(crate) fn record_literal_missing_fields(
223 &self,
224 db: &dyn HirDatabase,
225 literal: &ast::RecordLit,
226 ) -> Option<Vec<(StructField, Type)>> {
227 let krate = self.resolver.krate()?;
228 let body = self.body.as_ref()?;
229 let infer = self.infer.as_ref()?;
230
231 let expr_id = self.expr_id(db, &literal.clone().into())?;
232 let substs = match &infer.type_of_expr[expr_id] {
233 Ty::Apply(a_ty) => &a_ty.parameters,
234 _ => return None,
235 };
236
237 let (variant, missing_fields, _exhaustive) =
238 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
239 let res = self.missing_fields(db, krate, substs, variant, missing_fields);
240 Some(res)
241 }
242
243 pub(crate) fn record_pattern_missing_fields(
244 &self,
245 db: &dyn HirDatabase,
246 pattern: &ast::RecordPat,
247 ) -> Option<Vec<(StructField, Type)>> {
248 let krate = self.resolver.krate()?;
249 let body = self.body.as_ref()?;
250 let infer = self.infer.as_ref()?;
251
252 let pat_id = self.pat_id(&pattern.clone().into())?;
253 let substs = match &infer.type_of_pat[pat_id] {
254 Ty::Apply(a_ty) => &a_ty.parameters,
255 _ => return None,
256 };
257
258 let (variant, missing_fields) =
259 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
260 let res = self.missing_fields(db, krate, substs, variant, missing_fields);
261 Some(res)
262 }
263
264 fn missing_fields(
265 &self,
266 db: &dyn HirDatabase,
267 krate: CrateId,
268 substs: &Substs,
269 variant: VariantId,
270 missing_fields: Vec<LocalStructFieldId>,
271 ) -> Vec<(StructField, Type)> {
272 let field_types = db.field_types(variant);
273
274 missing_fields
275 .into_iter()
276 .map(|local_id| {
277 let field = StructFieldId { parent: variant, local_id };
278 let ty = field_types[local_id].clone().subst(substs);
279 (field.into(), Type::new_with_resolver_inner(db, krate, &self.resolver, ty))
280 })
281 .collect()
282 }
283
234 pub(crate) fn expand( 284 pub(crate) fn expand(
235 &self, 285 &self,
236 db: &dyn HirDatabase, 286 db: &dyn HirDatabase,