diff options
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 143 |
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 |
2 | use std::sync::Arc; | 2 | use std::{iter, sync::Arc}; |
3 | 3 | ||
4 | use arrayvec::ArrayVec; | 4 | use arrayvec::ArrayVec; |
5 | use either::Either; | 5 | use 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::{ | |||
25 | use hir_ty::{ | 26 | use 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 | }; |
34 | use ra_db::{CrateId, Edition, FileId}; | 32 | use ra_db::{CrateId, Edition, FileId}; |
35 | use ra_prof::profile; | 33 | use ra_prof::profile; |
36 | use ra_syntax::ast::{self, AttrsOwner, NameOwner}; | 34 | use ra_syntax::{ |
35 | ast::{self, AttrsOwner, NameOwner}, | ||
36 | AstNode, | ||
37 | }; | ||
37 | use rustc_hash::FxHashSet; | 38 | use rustc_hash::FxHashSet; |
39 | use stdx::impl_from; | ||
38 | 40 | ||
39 | use crate::{ | 41 | use 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 | } |
142 | impl_froms!( | 144 | impl_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 | ||
154 | impl ModuleDef { | 157 | impl ModuleDef { |
@@ -538,7 +541,7 @@ pub enum Adt { | |||
538 | Union(Union), | 541 | Union(Union), |
539 | Enum(Enum), | 542 | Enum(Enum), |
540 | } | 543 | } |
541 | impl_froms!(Adt: Struct, Union, Enum); | 544 | impl_from!(Struct, Union, Enum for Adt); |
542 | 545 | ||
543 | impl Adt { | 546 | impl 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 | } |
584 | impl_froms!(VariantDef: Struct, Union, EnumVariant); | 587 | impl_from!(Struct, Union, EnumVariant for VariantDef); |
585 | 588 | ||
586 | impl VariantDef { | 589 | impl 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 | 630 | impl_from!(Function, Const, Static for DefWithBody); | |
628 | impl_froms!(DefWithBody: Function, Const, Static); | ||
629 | 631 | ||
630 | impl DefWithBody { | 632 | impl 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 | } |
930 | impl_froms!( | 926 | impl_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 | ||
940 | impl GenericDef { | 937 | impl GenericDef { |
@@ -955,6 +952,16 @@ pub struct Local { | |||
955 | } | 952 | } |
956 | 953 | ||
957 | impl Local { | 954 | impl 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)] | ||
1529 | pub struct Callable { | ||
1530 | ty: Type, | ||
1531 | sig: FnSig, | ||
1532 | def: Option<CallableDefId>, | ||
1533 | pub(crate) is_bound_method: bool, | ||
1534 | } | ||
1535 | |||
1536 | pub enum CallableKind { | ||
1537 | Function(Function), | ||
1538 | TupleStruct(Struct), | ||
1539 | TupleEnumVariant(EnumVariant), | ||
1540 | Closure, | ||
1541 | } | ||
1542 | |||
1543 | impl 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)] |
1511 | pub enum ScopeDef { | 1597 | pub enum ScopeDef { |
@@ -1565,8 +1651,8 @@ pub enum AttrDef { | |||
1565 | MacroDef(MacroDef), | 1651 | MacroDef(MacroDef), |
1566 | } | 1652 | } |
1567 | 1653 | ||
1568 | impl_froms!( | 1654 | impl_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 | ||
1581 | pub trait HasAttrs { | 1668 | pub trait HasAttrs { |