aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs51
-rw-r--r--crates/ra_hir/src/diagnostics.rs2
-rw-r--r--crates/ra_hir/src/semantics.rs30
-rw-r--r--crates/ra_hir/src/semantics/source_to_def.rs18
-rw-r--r--crates/ra_hir/src/source_analyzer.rs90
5 files changed, 129 insertions, 62 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index cd2a8fc62..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 {
@@ -1084,6 +1092,26 @@ impl Type {
1084 ) 1092 )
1085 } 1093 }
1086 1094
1095 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1096 let trait_ref = hir_ty::TraitRef {
1097 trait_: trait_.id,
1098 substs: Substs::build_for_def(db, trait_.id)
1099 .push(self.ty.value.clone())
1100 .fill(args.iter().map(|t| t.ty.value.clone()))
1101 .build(),
1102 };
1103
1104 let goal = Canonical {
1105 value: hir_ty::InEnvironment::new(
1106 self.ty.environment.clone(),
1107 hir_ty::Obligation::Trait(trait_ref),
1108 ),
1109 num_vars: 0,
1110 };
1111
1112 db.trait_solve(self.krate, goal).is_some()
1113 }
1114
1087 // FIXME: this method is broken, as it doesn't take closures into account. 1115 // FIXME: this method is broken, as it doesn't take closures into account.
1088 pub fn as_callable(&self) -> Option<CallableDef> { 1116 pub fn as_callable(&self) -> Option<CallableDef> {
1089 Some(self.ty.value.as_callable()?.0) 1117 Some(self.ty.value.as_callable()?.0)
@@ -1132,27 +1160,6 @@ impl Type {
1132 res 1160 res
1133 } 1161 }
1134 1162
1135 pub fn variant_fields(
1136 &self,
1137 db: &dyn HirDatabase,
1138 def: VariantDef,
1139 ) -> Vec<(StructField, Type)> {
1140 // FIXME: check that ty and def match
1141 match &self.ty.value {
1142 Ty::Apply(a_ty) => {
1143 let field_types = db.field_types(def.into());
1144 def.fields(db)
1145 .into_iter()
1146 .map(|it| {
1147 let ty = field_types[it.id].clone().subst(&a_ty.parameters);
1148 (it, self.derived(ty))
1149 })
1150 .collect()
1151 }
1152 _ => Vec::new(),
1153 }
1154 }
1155
1156 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 {
1157 // There should be no inference vars in types passed here 1164 // There should be no inference vars in types passed here
1158 // FIXME check that? 1165 // FIXME check that?
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index a9040ea3d..c82883d0c 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2pub use hir_def::diagnostics::UnresolvedModule; 2pub use hir_def::diagnostics::UnresolvedModule;
3pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 3pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
4pub use hir_ty::diagnostics::{MissingFields, MissingOkInTailExpr, NoSuchField}; 4pub use hir_ty::diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField};
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 16a5fe968..2707e422d 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -9,6 +9,7 @@ use hir_def::{
9 AsMacroCall, TraitId, 9 AsMacroCall, TraitId,
10}; 10};
11use hir_expand::ExpansionInfo; 11use hir_expand::ExpansionInfo;
12use itertools::Itertools;
12use ra_db::{FileId, FileRange}; 13use ra_db::{FileId, FileRange};
13use ra_prof::profile; 14use ra_prof::profile;
14use ra_syntax::{ 15use ra_syntax::{
@@ -22,7 +23,7 @@ use crate::{
22 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 23 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
23 source_analyzer::{resolve_hir_path, SourceAnalyzer}, 24 source_analyzer::{resolve_hir_path, SourceAnalyzer},
24 AssocItem, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, Name, 25 AssocItem, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, Name,
25 Origin, Path, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, 26 Origin, Path, ScopeDef, StructField, Trait, Type, TypeParam,
26}; 27};
27 28
28#[derive(Debug, Clone, PartialEq, Eq)] 29#[derive(Debug, Clone, PartialEq, Eq)]
@@ -135,7 +136,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
135 node: &SyntaxNode, 136 node: &SyntaxNode,
136 offset: TextUnit, 137 offset: TextUnit,
137 ) -> impl Iterator<Item = SyntaxNode> + '_ { 138 ) -> impl Iterator<Item = SyntaxNode> + '_ {
138 use itertools::Itertools;
139 node.token_at_offset(offset) 139 node.token_at_offset(offset)
140 .map(|token| self.ancestors_with_macros(token.parent())) 140 .map(|token| self.ancestors_with_macros(token.parent()))
141 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) 141 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
@@ -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/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs
index 8843f2835..66724919b 100644
--- a/crates/ra_hir/src/semantics/source_to_def.rs
+++ b/crates/ra_hir/src/semantics/source_to_def.rs
@@ -208,12 +208,12 @@ impl SourceToDefCtx<'_, '_> {
208 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { 208 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
209 let res: GenericDefId = match_ast! { 209 let res: GenericDefId = match_ast! {
210 match (container.value) { 210 match (container.value) {
211 ast::FnDef(it) => { self.fn_to_def(container.with_value(it))?.into() }, 211 ast::FnDef(it) => self.fn_to_def(container.with_value(it))?.into(),
212 ast::StructDef(it) => { self.struct_to_def(container.with_value(it))?.into() }, 212 ast::StructDef(it) => self.struct_to_def(container.with_value(it))?.into(),
213 ast::EnumDef(it) => { self.enum_to_def(container.with_value(it))?.into() }, 213 ast::EnumDef(it) => self.enum_to_def(container.with_value(it))?.into(),
214 ast::TraitDef(it) => { self.trait_to_def(container.with_value(it))?.into() }, 214 ast::TraitDef(it) => self.trait_to_def(container.with_value(it))?.into(),
215 ast::TypeAliasDef(it) => { self.type_alias_to_def(container.with_value(it))?.into() }, 215 ast::TypeAliasDef(it) => self.type_alias_to_def(container.with_value(it))?.into(),
216 ast::ImplDef(it) => { self.impl_to_def(container.with_value(it))?.into() }, 216 ast::ImplDef(it) => self.impl_to_def(container.with_value(it))?.into(),
217 _ => continue, 217 _ => continue,
218 } 218 }
219 }; 219 };
@@ -226,9 +226,9 @@ impl SourceToDefCtx<'_, '_> {
226 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { 226 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
227 let res: DefWithBodyId = match_ast! { 227 let res: DefWithBodyId = match_ast! {
228 match (container.value) { 228 match (container.value) {
229 ast::ConstDef(it) => { self.const_to_def(container.with_value(it))?.into() }, 229 ast::ConstDef(it) => self.const_to_def(container.with_value(it))?.into(),
230 ast::StaticDef(it) => { self.static_to_def(container.with_value(it))?.into() }, 230 ast::StaticDef(it) => self.static_to_def(container.with_value(it))?.into(),
231 ast::FnDef(it) => { self.fn_to_def(container.with_value(it))?.into() }, 231 ast::FnDef(it) => self.fn_to_def(container.with_value(it))?.into(),
232 _ => continue, 232 _ => continue,
233 } 233 }
234 }; 234 };
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,