aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-07-16 12:00:56 +0100
committerAleksey Kladov <[email protected]>2020-07-16 17:03:04 +0100
commitff0312fa32715ce42f134fd9f049c4df5956d042 (patch)
treeb514e34d3486a650fef35e29396a810ee7741cd1 /crates/ra_hir/src
parent9210fcc076808e53e9bde84be26307fc0dc7d688 (diff)
Semantical call info
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs76
-rw-r--r--crates/ra_hir/src/lib.rs13
-rw-r--r--crates/ra_hir/src/semantics.rs25
-rw-r--r--crates/ra_hir/src/source_analyzer.rs6
4 files changed, 99 insertions, 21 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 9891b0785..057dfb82a 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,5 +1,5 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use std::sync::Arc; 2use std::{iter, sync::Arc};
3 3
4use arrayvec::ArrayVec; 4use arrayvec::ArrayVec;
5use either::Either; 5use either::Either;
@@ -12,6 +12,7 @@ use hir_def::{
12 import_map, 12 import_map,
13 per_ns::PerNs, 13 per_ns::PerNs,
14 resolver::{HasResolver, Resolver}, 14 resolver::{HasResolver, Resolver},
15 src::HasSource as _,
15 type_ref::{Mutability, TypeRef}, 16 type_ref::{Mutability, TypeRef},
16 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, 17 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule,
17 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, 18 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId,
@@ -25,8 +26,8 @@ use hir_expand::{
25use hir_ty::{ 26use hir_ty::{
26 autoderef, 27 autoderef,
27 display::{HirDisplayError, HirFormatter}, 28 display::{HirDisplayError, HirFormatter},
28 method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, 29 method_resolution, ApplicationTy, CallableDefId, Canonical, FnSig, GenericPredicate,
29 TraitEnvironment, Ty, TyDefId, TypeCtor, 30 InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
30}; 31};
31use ra_db::{CrateId, Edition, FileId}; 32use ra_db::{CrateId, Edition, FileId};
32use ra_prof::profile; 33use ra_prof::profile;
@@ -40,7 +41,7 @@ use stdx::impl_from;
40use crate::{ 41use crate::{
41 db::{DefDatabase, HirDatabase}, 42 db::{DefDatabase, HirDatabase},
42 has_source::HasSource, 43 has_source::HasSource,
43 CallableDefId, HirDisplay, InFile, Name, 44 HirDisplay, InFile, Name,
44}; 45};
45 46
46/// hir::Crate describes a single crate. It's the main interface with which 47/// hir::Crate describes a single crate. It's the main interface with which
@@ -1168,6 +1169,12 @@ impl Type {
1168 Type::new(db, krate, def, ty) 1169 Type::new(db, krate, def, ty)
1169 } 1170 }
1170 1171
1172 pub fn is_unit(&self) -> bool {
1173 matches!(
1174 self.ty.value,
1175 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. })
1176 )
1177 }
1171 pub fn is_bool(&self) -> bool { 1178 pub fn is_bool(&self) -> bool {
1172 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) 1179 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }))
1173 } 1180 }
@@ -1225,9 +1232,10 @@ impl Type {
1225 db.trait_solve(self.krate, goal).is_some() 1232 db.trait_solve(self.krate, goal).is_some()
1226 } 1233 }
1227 1234
1228 // FIXME: this method is broken, as it doesn't take closures into account. 1235 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1229 pub fn as_callable(&self) -> Option<CallableDefId> { 1236 let (id, substs) = self.ty.value.as_callable()?;
1230 Some(self.ty.value.as_callable()?.0) 1237 let sig = db.callable_item_signature(id).subst(substs);
1238 Some(Callable { ty: self.clone(), sig, id, is_bound_method: false })
1231 } 1239 }
1232 1240
1233 pub fn is_closure(&self) -> bool { 1241 pub fn is_closure(&self) -> bool {
@@ -1512,6 +1520,60 @@ impl HirDisplay for Type {
1512 } 1520 }
1513} 1521}
1514 1522
1523// FIXME: closures
1524#[derive(Debug)]
1525pub struct Callable {
1526 ty: Type,
1527 sig: FnSig,
1528 id: CallableDefId,
1529 pub(crate) is_bound_method: bool,
1530}
1531
1532pub enum CallableKind {
1533 Function(Function),
1534 TupleStruct(Struct),
1535 TupleEnumVariant(EnumVariant),
1536}
1537
1538impl Callable {
1539 pub fn kind(&self) -> CallableKind {
1540 match self.id {
1541 CallableDefId::FunctionId(it) => CallableKind::Function(it.into()),
1542 CallableDefId::StructId(it) => CallableKind::TupleStruct(it.into()),
1543 CallableDefId::EnumVariantId(it) => CallableKind::TupleEnumVariant(it.into()),
1544 }
1545 }
1546 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
1547 let func = match self.id {
1548 CallableDefId::FunctionId(it) if self.is_bound_method => it,
1549 _ => return None,
1550 };
1551 let src = func.lookup(db.upcast()).source(db.upcast());
1552 let param_list = src.value.param_list()?;
1553 param_list.self_param()
1554 }
1555 pub fn params(&self, db: &dyn HirDatabase) -> Vec<(Option<ast::Pat>, Type)> {
1556 let types = self
1557 .sig
1558 .params()
1559 .iter()
1560 .skip(if self.is_bound_method { 1 } else { 0 })
1561 .map(|ty| self.ty.derived(ty.clone()));
1562 let patterns = match self.id {
1563 CallableDefId::FunctionId(func) => {
1564 let src = func.lookup(db.upcast()).source(db.upcast());
1565 src.value.param_list().map(|it| it.params().map(|it| it.pat()))
1566 }
1567 CallableDefId::StructId(_) => None,
1568 CallableDefId::EnumVariantId(_) => None,
1569 };
1570 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
1571 }
1572 pub fn return_type(&self) -> Type {
1573 self.ty.derived(self.sig.ret().clone())
1574 }
1575}
1576
1515/// For IDE only 1577/// For IDE only
1516#[derive(Debug)] 1578#[derive(Debug)]
1517pub enum ScopeDef { 1579pub enum ScopeDef {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index cf7134923..31f3241c9 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -32,10 +32,10 @@ mod has_source;
32 32
33pub use crate::{ 33pub use crate::{
34 code_model::{ 34 code_model::{
35 Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency, 35 Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, Const,
36 DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, GenericDef, HasAttrs, 36 Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function,
37 HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, 37 GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef,
38 Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 38 Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
39 }, 39 },
40 has_source::HasSource, 40 has_source::HasSource,
41 semantics::{original_range, PathResolution, Semantics, SemanticsScope}, 41 semantics::{original_range, PathResolution, Semantics, SemanticsScope},
@@ -52,7 +52,8 @@ pub use hir_def::{
52 type_ref::Mutability, 52 type_ref::Mutability,
53}; 53};
54pub use hir_expand::{ 54pub use hir_expand::{
55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, 55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc,
56 MacroDefId, /* FIXME */
56 MacroFile, Origin, 57 MacroFile, Origin,
57}; 58};
58pub use hir_ty::{display::HirDisplay, CallableDefId}; 59pub use hir_ty::display::HirDisplay;
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 155b666d7..f5283ab22 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -6,7 +6,7 @@ use std::{cell::RefCell, fmt, iter::successors};
6 6
7use hir_def::{ 7use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, TraitId, VariantId, 9 AsMacroCall, FunctionId, TraitId, VariantId,
10}; 10};
11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; 11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
@@ -24,8 +24,8 @@ use crate::{
24 diagnostics::Diagnostic, 24 diagnostics::Diagnostic,
25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, 26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer},
27 AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, 27 AssocItem, Callable, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module,
28 Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, 28 ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef,
29}; 29};
30use resolver::TypeNs; 30use resolver::TypeNs;
31 31
@@ -197,7 +197,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
197 } 197 }
198 198
199 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 199 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
200 self.imp.resolve_method_call(call) 200 self.imp.resolve_method_call(call).map(Function::from)
201 }
202
203 pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
204 self.imp.resolve_method_call_as_callable(call)
201 } 205 }
202 206
203 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { 207 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
@@ -385,10 +389,21 @@ impl<'db> SemanticsImpl<'db> {
385 self.analyze(param.syntax()).type_of_self(self.db, &param) 389 self.analyze(param.syntax()).type_of_self(self.db, &param)
386 } 390 }
387 391
388 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 392 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
389 self.analyze(call.syntax()).resolve_method_call(self.db, call) 393 self.analyze(call.syntax()).resolve_method_call(self.db, call)
390 } 394 }
391 395
396 fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
397 // FIXME: this erases Substs
398 let func = self.resolve_method_call(call)?;
399 let ty = self.db.value_ty(func.into());
400 let resolver = self.analyze(call.syntax()).resolver;
401 let ty = Type::new_with_resolver(self.db, &resolver, ty.value)?;
402 let mut res = ty.as_callable(self.db)?;
403 res.is_bound_method = true;
404 Some(res)
405 }
406
392 fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { 407 fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
393 self.analyze(field.syntax()).resolve_field(self.db, field) 408 self.analyze(field.syntax()).resolve_field(self.db, field)
394 } 409 }
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index ecb54f653..86a47a9e5 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -14,7 +14,7 @@ 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, FieldId, LocalFieldId, VariantId, 17 AsMacroCall, DefWithBodyId, FieldId, FunctionId, LocalFieldId, VariantId,
18}; 18};
19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
20use hir_ty::{ 20use hir_ty::{
@@ -142,9 +142,9 @@ impl SourceAnalyzer {
142 &self, 142 &self,
143 db: &dyn HirDatabase, 143 db: &dyn HirDatabase,
144 call: &ast::MethodCallExpr, 144 call: &ast::MethodCallExpr,
145 ) -> Option<Function> { 145 ) -> Option<FunctionId> {
146 let expr_id = self.expr_id(db, &call.clone().into())?; 146 let expr_id = self.expr_id(db, &call.clone().into())?;
147 self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) 147 self.infer.as_ref()?.method_resolution(expr_id)
148 } 148 }
149 149
150 pub(crate) fn resolve_field( 150 pub(crate) fn resolve_field(