diff options
author | Zac Pullar-Strecker <[email protected]> | 2020-07-31 03:12:44 +0100 |
---|---|---|
committer | Zac Pullar-Strecker <[email protected]> | 2020-07-31 03:12:44 +0100 |
commit | f05d7b41a719d848844b054a16477b29d0f063c6 (patch) | |
tree | 0a8a0946e8aef2ce64d4c13d0035ba41cce2daf3 /crates/ra_hir/src/code_model.rs | |
parent | 73ff610e41959e3e7c78a2b4b25b086883132956 (diff) | |
parent | 6b7cb8b5ab539fc4333ce34bc29bf77c976f232a (diff) |
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Hasn't fixed tests yet.
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 179 |
1 files changed, 134 insertions, 45 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 8c5e1b746..5d88c5c64 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, CrateName, 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 |
@@ -94,8 +96,8 @@ impl Crate { | |||
94 | db.crate_graph()[self.id].edition | 96 | db.crate_graph()[self.id].edition |
95 | } | 97 | } |
96 | 98 | ||
97 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateName> { | 99 | pub fn display_name(self, db: &dyn HirDatabase) -> Option<String> { |
98 | db.crate_graph()[self.id].display_name.as_ref().cloned() | 100 | db.crate_graph()[self.id].display_name.clone() |
99 | } | 101 | } |
100 | 102 | ||
101 | pub fn query_external_importables( | 103 | pub fn query_external_importables( |
@@ -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 { |
@@ -376,8 +379,8 @@ pub struct Field { | |||
376 | 379 | ||
377 | #[derive(Debug, PartialEq, Eq)] | 380 | #[derive(Debug, PartialEq, Eq)] |
378 | pub enum FieldSource { | 381 | pub enum FieldSource { |
379 | Named(ast::RecordFieldDef), | 382 | Named(ast::RecordField), |
380 | Pos(ast::TupleFieldDef), | 383 | Pos(ast::TupleField), |
381 | } | 384 | } |
382 | 385 | ||
383 | impl Field { | 386 | impl Field { |
@@ -556,7 +559,7 @@ pub enum Adt { | |||
556 | Union(Union), | 559 | Union(Union), |
557 | Enum(Enum), | 560 | Enum(Enum), |
558 | } | 561 | } |
559 | impl_froms!(Adt: Struct, Union, Enum); | 562 | impl_from!(Struct, Union, Enum for Adt); |
560 | 563 | ||
561 | impl Adt { | 564 | impl Adt { |
562 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 565 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
@@ -599,7 +602,7 @@ pub enum VariantDef { | |||
599 | Union(Union), | 602 | Union(Union), |
600 | EnumVariant(EnumVariant), | 603 | EnumVariant(EnumVariant), |
601 | } | 604 | } |
602 | impl_froms!(VariantDef: Struct, Union, EnumVariant); | 605 | impl_from!(Struct, Union, EnumVariant for VariantDef); |
603 | 606 | ||
604 | impl VariantDef { | 607 | impl VariantDef { |
605 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { | 608 | pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> { |
@@ -642,8 +645,7 @@ pub enum DefWithBody { | |||
642 | Static(Static), | 645 | Static(Static), |
643 | Const(Const), | 646 | Const(Const), |
644 | } | 647 | } |
645 | 648 | impl_from!(Function, Const, Static for DefWithBody); | |
646 | impl_froms!(DefWithBody: Function, Const, Static); | ||
647 | 649 | ||
648 | impl DefWithBody { | 650 | impl DefWithBody { |
649 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 651 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
@@ -694,13 +696,7 @@ impl Function { | |||
694 | } | 696 | } |
695 | 697 | ||
696 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 698 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
697 | let _p = profile("Function::diagnostics"); | 699 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink) |
698 | let infer = db.infer(self.id.into()); | ||
699 | infer.add_diagnostics(db, self.id, sink); | ||
700 | let mut validator = ExprValidator::new(self.id, infer.clone(), sink); | ||
701 | validator.validate_body(db); | ||
702 | let mut validator = UnsafeValidator::new(self.id, infer, sink); | ||
703 | validator.validate_body(db); | ||
704 | } | 700 | } |
705 | } | 701 | } |
706 | 702 | ||
@@ -945,14 +941,15 @@ pub enum GenericDef { | |||
945 | // consts can have type parameters from their parents (i.e. associated consts of traits) | 941 | // consts can have type parameters from their parents (i.e. associated consts of traits) |
946 | Const(Const), | 942 | Const(Const), |
947 | } | 943 | } |
948 | impl_froms!( | 944 | impl_from!( |
949 | GenericDef: Function, | 945 | Function, |
950 | Adt(Struct, Enum, Union), | 946 | Adt(Struct, Enum, Union), |
951 | Trait, | 947 | Trait, |
952 | TypeAlias, | 948 | TypeAlias, |
953 | ImplDef, | 949 | ImplDef, |
954 | EnumVariant, | 950 | EnumVariant, |
955 | Const | 951 | Const |
952 | for GenericDef | ||
956 | ); | 953 | ); |
957 | 954 | ||
958 | impl GenericDef { | 955 | impl GenericDef { |
@@ -973,6 +970,16 @@ pub struct Local { | |||
973 | } | 970 | } |
974 | 971 | ||
975 | impl Local { | 972 | impl Local { |
973 | pub fn is_param(self, db: &dyn HirDatabase) -> bool { | ||
974 | let src = self.source(db); | ||
975 | match src.value { | ||
976 | Either::Left(bind_pat) => { | ||
977 | bind_pat.syntax().ancestors().any(|it| ast::Param::can_cast(it.kind())) | ||
978 | } | ||
979 | Either::Right(_self_param) => true, | ||
980 | } | ||
981 | } | ||
982 | |||
976 | // FIXME: why is this an option? It shouldn't be? | 983 | // FIXME: why is this an option? It shouldn't be? |
977 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 984 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
978 | let body = db.body(self.parent.into()); | 985 | let body = db.body(self.parent.into()); |
@@ -1071,12 +1078,14 @@ pub struct ImplDef { | |||
1071 | 1078 | ||
1072 | impl ImplDef { | 1079 | impl ImplDef { |
1073 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { | 1080 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { |
1074 | let impls = db.impls_in_crate(krate.id); | 1081 | let inherent = db.inherent_impls_in_crate(krate.id); |
1075 | impls.all_impls().map(Self::from).collect() | 1082 | let trait_ = db.trait_impls_in_crate(krate.id); |
1083 | |||
1084 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | ||
1076 | } | 1085 | } |
1077 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { | 1086 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { |
1078 | let impls = db.impls_in_crate(krate.id); | 1087 | let impls = db.trait_impls_in_crate(krate.id); |
1079 | impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() | 1088 | impls.for_trait(trait_.id).map(Self::from).collect() |
1080 | } | 1089 | } |
1081 | 1090 | ||
1082 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1091 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
@@ -1178,6 +1187,12 @@ impl Type { | |||
1178 | Type::new(db, krate, def, ty) | 1187 | Type::new(db, krate, def, ty) |
1179 | } | 1188 | } |
1180 | 1189 | ||
1190 | pub fn is_unit(&self) -> bool { | ||
1191 | matches!( | ||
1192 | self.ty.value, | ||
1193 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. }) | ||
1194 | ) | ||
1195 | } | ||
1181 | pub fn is_bool(&self) -> bool { | 1196 | pub fn is_bool(&self) -> bool { |
1182 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) | 1197 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) |
1183 | } | 1198 | } |
@@ -1205,7 +1220,7 @@ impl Type { | |||
1205 | None => return false, | 1220 | None => return false, |
1206 | }; | 1221 | }; |
1207 | 1222 | ||
1208 | let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1223 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1209 | method_resolution::implements_trait( | 1224 | method_resolution::implements_trait( |
1210 | &canonical_ty, | 1225 | &canonical_ty, |
1211 | db, | 1226 | db, |
@@ -1229,15 +1244,20 @@ impl Type { | |||
1229 | self.ty.environment.clone(), | 1244 | self.ty.environment.clone(), |
1230 | hir_ty::Obligation::Trait(trait_ref), | 1245 | hir_ty::Obligation::Trait(trait_ref), |
1231 | ), | 1246 | ), |
1232 | num_vars: 0, | 1247 | kinds: Arc::new([]), |
1233 | }; | 1248 | }; |
1234 | 1249 | ||
1235 | db.trait_solve(self.krate, goal).is_some() | 1250 | db.trait_solve(self.krate, goal).is_some() |
1236 | } | 1251 | } |
1237 | 1252 | ||
1238 | // FIXME: this method is broken, as it doesn't take closures into account. | 1253 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { |
1239 | pub fn as_callable(&self) -> Option<CallableDef> { | 1254 | let def = match self.ty.value { |
1240 | Some(self.ty.value.as_callable()?.0) | 1255 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), |
1256 | _ => None, | ||
1257 | }; | ||
1258 | |||
1259 | let sig = self.ty.value.callable_sig(db)?; | ||
1260 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) | ||
1241 | } | 1261 | } |
1242 | 1262 | ||
1243 | pub fn is_closure(&self) -> bool { | 1263 | pub fn is_closure(&self) -> bool { |
@@ -1304,7 +1324,7 @@ impl Type { | |||
1304 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { | 1324 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { |
1305 | // There should be no inference vars in types passed here | 1325 | // There should be no inference vars in types passed here |
1306 | // FIXME check that? | 1326 | // FIXME check that? |
1307 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1327 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1308 | let environment = self.ty.environment.clone(); | 1328 | let environment = self.ty.environment.clone(); |
1309 | let ty = InEnvironment { value: canonical, environment }; | 1329 | let ty = InEnvironment { value: canonical, environment }; |
1310 | autoderef(db, Some(self.krate), ty) | 1330 | autoderef(db, Some(self.krate), ty) |
@@ -1321,10 +1341,10 @@ impl Type { | |||
1321 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 1341 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
1322 | ) -> Option<T> { | 1342 | ) -> Option<T> { |
1323 | for krate in self.ty.value.def_crates(db, krate.id)? { | 1343 | for krate in self.ty.value.def_crates(db, krate.id)? { |
1324 | let impls = db.impls_in_crate(krate); | 1344 | let impls = db.inherent_impls_in_crate(krate); |
1325 | 1345 | ||
1326 | for impl_def in impls.lookup_impl_defs(&self.ty.value) { | 1346 | for impl_def in impls.for_self_ty(&self.ty.value) { |
1327 | for &item in db.impl_data(impl_def).items.iter() { | 1347 | for &item in db.impl_data(*impl_def).items.iter() { |
1328 | if let Some(result) = callback(item.into()) { | 1348 | if let Some(result) = callback(item.into()) { |
1329 | return Some(result); | 1349 | return Some(result); |
1330 | } | 1350 | } |
@@ -1345,7 +1365,7 @@ impl Type { | |||
1345 | // There should be no inference vars in types passed here | 1365 | // There should be no inference vars in types passed here |
1346 | // FIXME check that? | 1366 | // FIXME check that? |
1347 | // FIXME replace Unknown by bound vars here | 1367 | // FIXME replace Unknown by bound vars here |
1348 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1368 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1349 | 1369 | ||
1350 | let env = self.ty.environment.clone(); | 1370 | let env = self.ty.environment.clone(); |
1351 | let krate = krate.id; | 1371 | let krate = krate.id; |
@@ -1376,7 +1396,7 @@ impl Type { | |||
1376 | // There should be no inference vars in types passed here | 1396 | // There should be no inference vars in types passed here |
1377 | // FIXME check that? | 1397 | // FIXME check that? |
1378 | // FIXME replace Unknown by bound vars here | 1398 | // FIXME replace Unknown by bound vars here |
1379 | let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | 1399 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; |
1380 | 1400 | ||
1381 | let env = self.ty.environment.clone(); | 1401 | let env = self.ty.environment.clone(); |
1382 | let krate = krate.id; | 1402 | let krate = krate.id; |
@@ -1522,6 +1542,74 @@ impl HirDisplay for Type { | |||
1522 | } | 1542 | } |
1523 | } | 1543 | } |
1524 | 1544 | ||
1545 | // FIXME: closures | ||
1546 | #[derive(Debug)] | ||
1547 | pub struct Callable { | ||
1548 | ty: Type, | ||
1549 | sig: FnSig, | ||
1550 | def: Option<CallableDefId>, | ||
1551 | pub(crate) is_bound_method: bool, | ||
1552 | } | ||
1553 | |||
1554 | pub enum CallableKind { | ||
1555 | Function(Function), | ||
1556 | TupleStruct(Struct), | ||
1557 | TupleEnumVariant(EnumVariant), | ||
1558 | Closure, | ||
1559 | } | ||
1560 | |||
1561 | impl Callable { | ||
1562 | pub fn kind(&self) -> CallableKind { | ||
1563 | match self.def { | ||
1564 | Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()), | ||
1565 | Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()), | ||
1566 | Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()), | ||
1567 | None => CallableKind::Closure, | ||
1568 | } | ||
1569 | } | ||
1570 | pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> { | ||
1571 | let func = match self.def { | ||
1572 | Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it, | ||
1573 | _ => return None, | ||
1574 | }; | ||
1575 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
1576 | let param_list = src.value.param_list()?; | ||
1577 | param_list.self_param() | ||
1578 | } | ||
1579 | pub fn n_params(&self) -> usize { | ||
1580 | self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } | ||
1581 | } | ||
1582 | pub fn params( | ||
1583 | &self, | ||
1584 | db: &dyn HirDatabase, | ||
1585 | ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> { | ||
1586 | let types = self | ||
1587 | .sig | ||
1588 | .params() | ||
1589 | .iter() | ||
1590 | .skip(if self.is_bound_method { 1 } else { 0 }) | ||
1591 | .map(|ty| self.ty.derived(ty.clone())); | ||
1592 | let patterns = match self.def { | ||
1593 | Some(CallableDefId::FunctionId(func)) => { | ||
1594 | let src = func.lookup(db.upcast()).source(db.upcast()); | ||
1595 | src.value.param_list().map(|param_list| { | ||
1596 | param_list | ||
1597 | .self_param() | ||
1598 | .map(|it| Some(Either::Left(it))) | ||
1599 | .filter(|_| !self.is_bound_method) | ||
1600 | .into_iter() | ||
1601 | .chain(param_list.params().map(|it| it.pat().map(Either::Right))) | ||
1602 | }) | ||
1603 | } | ||
1604 | _ => None, | ||
1605 | }; | ||
1606 | patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect() | ||
1607 | } | ||
1608 | pub fn return_type(&self) -> Type { | ||
1609 | self.ty.derived(self.sig.ret().clone()) | ||
1610 | } | ||
1611 | } | ||
1612 | |||
1525 | /// For IDE only | 1613 | /// For IDE only |
1526 | #[derive(Debug)] | 1614 | #[derive(Debug)] |
1527 | pub enum ScopeDef { | 1615 | pub enum ScopeDef { |
@@ -1581,8 +1669,8 @@ pub enum AttrDef { | |||
1581 | MacroDef(MacroDef), | 1669 | MacroDef(MacroDef), |
1582 | } | 1670 | } |
1583 | 1671 | ||
1584 | impl_froms!( | 1672 | impl_from!( |
1585 | AttrDef: Module, | 1673 | Module, |
1586 | Field, | 1674 | Field, |
1587 | Adt(Struct, Enum, Union), | 1675 | Adt(Struct, Enum, Union), |
1588 | EnumVariant, | 1676 | EnumVariant, |
@@ -1592,6 +1680,7 @@ impl_froms!( | |||
1592 | Trait, | 1680 | Trait, |
1593 | TypeAlias, | 1681 | TypeAlias, |
1594 | MacroDef | 1682 | MacroDef |
1683 | for AttrDef | ||
1595 | ); | 1684 | ); |
1596 | 1685 | ||
1597 | pub trait HasAttrs { | 1686 | pub trait HasAttrs { |