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.rs143
1 files changed, 115 insertions, 28 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 1b3525011..859bdfb3b 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,21 +26,22 @@ use hir_expand::{
25use hir_ty::{ 26use hir_ty::{
26 autoderef, 27 autoderef,
27 display::{HirDisplayError, HirFormatter}, 28 display::{HirDisplayError, HirFormatter},
28 expr::ExprValidator, 29 method_resolution, ApplicationTy, CallableDefId, Canonical, FnSig, GenericPredicate,
29 method_resolution, 30 InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
30 unsafe_validation::UnsafeValidator,
31 ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, TraitEnvironment, Ty,
32 TyDefId, TypeCtor,
33}; 31};
34use ra_db::{CrateId, Edition, FileId}; 32use ra_db::{CrateId, Edition, FileId};
35use ra_prof::profile; 33use ra_prof::profile;
36use ra_syntax::ast::{self, AttrsOwner, NameOwner}; 34use ra_syntax::{
35 ast::{self, AttrsOwner, NameOwner},
36 AstNode,
37};
37use rustc_hash::FxHashSet; 38use rustc_hash::FxHashSet;
39use stdx::impl_from;
38 40
39use crate::{ 41use crate::{
40 db::{DefDatabase, HirDatabase}, 42 db::{DefDatabase, HirDatabase},
41 has_source::HasSource, 43 has_source::HasSource,
42 CallableDef, HirDisplay, InFile, Name, 44 HirDisplay, InFile, Name,
43}; 45};
44 46
45/// 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
@@ -139,8 +141,8 @@ pub enum ModuleDef {
139 TypeAlias(TypeAlias), 141 TypeAlias(TypeAlias),
140 BuiltinType(BuiltinType), 142 BuiltinType(BuiltinType),
141} 143}
142impl_froms!( 144impl_from!(
143 ModuleDef: Module, 145 Module,
144 Function, 146 Function,
145 Adt(Struct, Enum, Union), 147 Adt(Struct, Enum, Union),
146 EnumVariant, 148 EnumVariant,
@@ -149,6 +151,7 @@ impl_froms!(
149 Trait, 151 Trait,
150 TypeAlias, 152 TypeAlias,
151 BuiltinType 153 BuiltinType
154 for ModuleDef
152); 155);
153 156
154impl ModuleDef { 157impl ModuleDef {
@@ -538,7 +541,7 @@ pub enum Adt {
538 Union(Union), 541 Union(Union),
539 Enum(Enum), 542 Enum(Enum),
540} 543}
541impl_froms!(Adt: Struct, Union, Enum); 544impl_from!(Struct, Union, Enum for Adt);
542 545
543impl Adt { 546impl Adt {
544 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 547 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
@@ -581,7 +584,7 @@ pub enum VariantDef {
581 Union(Union), 584 Union(Union),
582 EnumVariant(EnumVariant), 585 EnumVariant(EnumVariant),
583} 586}
584impl_froms!(VariantDef: Struct, Union, EnumVariant); 587impl_from!(Struct, Union, EnumVariant for VariantDef);
585 588
586impl VariantDef { 589impl VariantDef {
587 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { 590 pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
@@ -624,8 +627,7 @@ pub enum DefWithBody {
624 Static(Static), 627 Static(Static),
625 Const(Const), 628 Const(Const),
626} 629}
627 630impl_from!(Function, Const, Static for DefWithBody);
628impl_froms!(DefWithBody: Function, Const, Static);
629 631
630impl DefWithBody { 632impl DefWithBody {
631 pub fn module(self, db: &dyn HirDatabase) -> Module { 633 pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -676,13 +678,7 @@ impl Function {
676 } 678 }
677 679
678 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 680 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
679 let _p = profile("Function::diagnostics"); 681 hir_ty::diagnostics::validate_body(db, self.id.into(), sink)
680 let infer = db.infer(self.id.into());
681 infer.add_diagnostics(db, self.id, sink);
682 let mut validator = ExprValidator::new(self.id, infer.clone(), sink);
683 validator.validate_body(db);
684 let mut validator = UnsafeValidator::new(self.id, infer, sink);
685 validator.validate_body(db);
686 } 682 }
687} 683}
688 684
@@ -927,14 +923,15 @@ pub enum GenericDef {
927 // consts can have type parameters from their parents (i.e. associated consts of traits) 923 // consts can have type parameters from their parents (i.e. associated consts of traits)
928 Const(Const), 924 Const(Const),
929} 925}
930impl_froms!( 926impl_from!(
931 GenericDef: Function, 927 Function,
932 Adt(Struct, Enum, Union), 928 Adt(Struct, Enum, Union),
933 Trait, 929 Trait,
934 TypeAlias, 930 TypeAlias,
935 ImplDef, 931 ImplDef,
936 EnumVariant, 932 EnumVariant,
937 Const 933 Const
934 for GenericDef
938); 935);
939 936
940impl GenericDef { 937impl GenericDef {
@@ -955,6 +952,16 @@ pub struct Local {
955} 952}
956 953
957impl Local { 954impl Local {
955 pub fn is_param(self, db: &dyn HirDatabase) -> bool {
956 let src = self.source(db);
957 match src.value {
958 Either::Left(bind_pat) => {
959 bind_pat.syntax().ancestors().any(|it| ast::Param::can_cast(it.kind()))
960 }
961 Either::Right(_self_param) => true,
962 }
963 }
964
958 // FIXME: why is this an option? It shouldn't be? 965 // FIXME: why is this an option? It shouldn't be?
959 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 966 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
960 let body = db.body(self.parent.into()); 967 let body = db.body(self.parent.into());
@@ -1162,6 +1169,12 @@ impl Type {
1162 Type::new(db, krate, def, ty) 1169 Type::new(db, krate, def, ty)
1163 } 1170 }
1164 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 }
1165 pub fn is_bool(&self) -> bool { 1178 pub fn is_bool(&self) -> bool {
1166 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) 1179 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }))
1167 } 1180 }
@@ -1219,9 +1232,14 @@ impl Type {
1219 db.trait_solve(self.krate, goal).is_some() 1232 db.trait_solve(self.krate, goal).is_some()
1220 } 1233 }
1221 1234
1222 // FIXME: this method is broken, as it doesn't take closures into account. 1235 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1223 pub fn as_callable(&self) -> Option<CallableDef> { 1236 let def = match self.ty.value {
1224 Some(self.ty.value.as_callable()?.0) 1237 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
1238 _ => None,
1239 };
1240
1241 let sig = self.ty.value.callable_sig(db)?;
1242 Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
1225 } 1243 }
1226 1244
1227 pub fn is_closure(&self) -> bool { 1245 pub fn is_closure(&self) -> bool {
@@ -1506,6 +1524,74 @@ impl HirDisplay for Type {
1506 } 1524 }
1507} 1525}
1508 1526
1527// FIXME: closures
1528#[derive(Debug)]
1529pub struct Callable {
1530 ty: Type,
1531 sig: FnSig,
1532 def: Option<CallableDefId>,
1533 pub(crate) is_bound_method: bool,
1534}
1535
1536pub enum CallableKind {
1537 Function(Function),
1538 TupleStruct(Struct),
1539 TupleEnumVariant(EnumVariant),
1540 Closure,
1541}
1542
1543impl Callable {
1544 pub fn kind(&self) -> CallableKind {
1545 match self.def {
1546 Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
1547 Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
1548 Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
1549 None => CallableKind::Closure,
1550 }
1551 }
1552 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
1553 let func = match self.def {
1554 Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
1555 _ => return None,
1556 };
1557 let src = func.lookup(db.upcast()).source(db.upcast());
1558 let param_list = src.value.param_list()?;
1559 param_list.self_param()
1560 }
1561 pub fn n_params(&self) -> usize {
1562 self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
1563 }
1564 pub fn params(
1565 &self,
1566 db: &dyn HirDatabase,
1567 ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
1568 let types = self
1569 .sig
1570 .params()
1571 .iter()
1572 .skip(if self.is_bound_method { 1 } else { 0 })
1573 .map(|ty| self.ty.derived(ty.clone()));
1574 let patterns = match self.def {
1575 Some(CallableDefId::FunctionId(func)) => {
1576 let src = func.lookup(db.upcast()).source(db.upcast());
1577 src.value.param_list().map(|param_list| {
1578 param_list
1579 .self_param()
1580 .map(|it| Some(Either::Left(it)))
1581 .filter(|_| !self.is_bound_method)
1582 .into_iter()
1583 .chain(param_list.params().map(|it| it.pat().map(Either::Right)))
1584 })
1585 }
1586 _ => None,
1587 };
1588 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
1589 }
1590 pub fn return_type(&self) -> Type {
1591 self.ty.derived(self.sig.ret().clone())
1592 }
1593}
1594
1509/// For IDE only 1595/// For IDE only
1510#[derive(Debug)] 1596#[derive(Debug)]
1511pub enum ScopeDef { 1597pub enum ScopeDef {
@@ -1565,8 +1651,8 @@ pub enum AttrDef {
1565 MacroDef(MacroDef), 1651 MacroDef(MacroDef),
1566} 1652}
1567 1653
1568impl_froms!( 1654impl_from!(
1569 AttrDef: Module, 1655 Module,
1570 Field, 1656 Field,
1571 Adt(Struct, Enum, Union), 1657 Adt(Struct, Enum, Union),
1572 EnumVariant, 1658 EnumVariant,
@@ -1576,6 +1662,7 @@ impl_froms!(
1576 Trait, 1662 Trait,
1577 TypeAlias, 1663 TypeAlias,
1578 MacroDef 1664 MacroDef
1665 for AttrDef
1579); 1666);
1580 1667
1581pub trait HasAttrs { 1668pub trait HasAttrs {