aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs86
1 files changed, 79 insertions, 7 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 9891b0785..eb6a14eda 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,70 @@ 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(
1556 &self,
1557 db: &dyn HirDatabase,
1558 ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
1559 let types = self
1560 .sig
1561 .params()
1562 .iter()
1563 .skip(if self.is_bound_method { 1 } else { 0 })
1564 .map(|ty| self.ty.derived(ty.clone()));
1565 let patterns = match self.id {
1566 CallableDefId::FunctionId(func) => {
1567 let src = func.lookup(db.upcast()).source(db.upcast());
1568 src.value.param_list().map(|param_list| {
1569 param_list
1570 .self_param()
1571 .map(|it| Some(Either::Left(it)))
1572 .filter(|_| !self.is_bound_method)
1573 .into_iter()
1574 .chain(param_list.params().map(|it| it.pat().map(Either::Right)))
1575 })
1576 }
1577 CallableDefId::StructId(_) => None,
1578 CallableDefId::EnumVariantId(_) => None,
1579 };
1580 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
1581 }
1582 pub fn return_type(&self) -> Type {
1583 self.ty.derived(self.sig.ret().clone())
1584 }
1585}
1586
1515/// For IDE only 1587/// For IDE only
1516#[derive(Debug)] 1588#[derive(Debug)]
1517pub enum ScopeDef { 1589pub enum ScopeDef {