aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/Cargo.toml2
-rw-r--r--crates/ra_hir/src/code_model.rs143
-rw-r--r--crates/ra_hir/src/db.rs6
-rw-r--r--crates/ra_hir/src/diagnostics.rs4
-rw-r--r--crates/ra_hir/src/lib.rs32
-rw-r--r--crates/ra_hir/src/semantics.rs99
-rw-r--r--crates/ra_hir/src/semantics/source_to_def.rs12
-rw-r--r--crates/ra_hir/src/source_analyzer.rs23
8 files changed, 219 insertions, 102 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index ba7b39a19..c260bb193 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -3,6 +3,7 @@ edition = "2018"
3name = "ra_hir" 3name = "ra_hir"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6license = "MIT OR Apache-2.0"
6 7
7[lib] 8[lib]
8doctest = false 9doctest = false
@@ -15,6 +16,7 @@ arrayvec = "0.5.1"
15 16
16itertools = "0.9.0" 17itertools = "0.9.0"
17 18
19stdx = { path = "../stdx" }
18ra_syntax = { path = "../ra_syntax" } 20ra_syntax = { path = "../ra_syntax" }
19ra_db = { path = "../ra_db" } 21ra_db = { path = "../ra_db" }
20ra_prof = { path = "../ra_prof" } 22ra_prof = { path = "../ra_prof" }
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 {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index cb48ca065..1ad92a1f8 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -17,9 +17,9 @@ pub use hir_ty::db::{
17 AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, 17 AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery,
18 GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, 18 GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase,
19 HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery, 19 HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery,
20 InherentImplsInCrateQuery, InternAssocTyValueQuery, InternChalkImplQuery, InternTypeCtorQuery, 20 InherentImplsInCrateQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
21 InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, TraitDatumQuery, 21 TraitDatumQuery, TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery,
22 TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, ValueTyQuery, 22 ValueTyQuery,
23}; 23};
24 24
25#[test] 25#[test]
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index c82883d0c..11a0ecb8b 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,4 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2pub use hir_def::diagnostics::UnresolvedModule; 2pub use hir_def::diagnostics::UnresolvedModule;
3pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 3pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
4pub use hir_ty::diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField}; 4pub use hir_ty::diagnostics::{
5 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField,
6};
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 3364a822f..31f3241c9 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -19,25 +19,6 @@
19 19
20#![recursion_limit = "512"] 20#![recursion_limit = "512"]
21 21
22macro_rules! impl_froms {
23 ($e:ident: $($v:ident $(($($sv:ident),*))?),*$(,)?) => {
24 $(
25 impl From<$v> for $e {
26 fn from(it: $v) -> $e {
27 $e::$v(it)
28 }
29 }
30 $($(
31 impl From<$sv> for $e {
32 fn from(it: $sv) -> $e {
33 $e::$v($v::$sv(it))
34 }
35 }
36 )*)?
37 )*
38 }
39}
40
41mod semantics; 22mod semantics;
42pub mod db; 23pub mod db;
43mod source_analyzer; 24mod source_analyzer;
@@ -51,10 +32,10 @@ mod has_source;
51 32
52pub use crate::{ 33pub use crate::{
53 code_model::{ 34 code_model::{
54 Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency, 35 Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, Const,
55 DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, GenericDef, HasAttrs, 36 Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function,
56 HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, 37 GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef,
57 Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 38 Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
58 }, 39 },
59 has_source::HasSource, 40 has_source::HasSource,
60 semantics::{original_range, PathResolution, Semantics, SemanticsScope}, 41 semantics::{original_range, PathResolution, Semantics, SemanticsScope},
@@ -71,7 +52,8 @@ pub use hir_def::{
71 type_ref::Mutability, 52 type_ref::Mutability,
72}; 53};
73pub use hir_expand::{ 54pub use hir_expand::{
74 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, 55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc,
56 MacroDefId, /* FIXME */
75 MacroFile, Origin, 57 MacroFile, Origin,
76}; 58};
77pub use hir_ty::{display::HirDisplay, CallableDef}; 59pub use hir_ty::display::HirDisplay;
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 3d78f71c1..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, 28 ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef,
29}; 29};
30use resolver::TypeNs; 30use resolver::TypeNs;
31 31
@@ -192,8 +192,16 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
192 self.imp.type_of_pat(pat) 192 self.imp.type_of_pat(pat)
193 } 193 }
194 194
195 pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
196 self.imp.type_of_self(param)
197 }
198
195 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 199 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
196 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)
197 } 205 }
198 206
199 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { 207 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
@@ -216,8 +224,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
216 self.imp.resolve_path(path) 224 self.imp.resolve_path(path)
217 } 225 }
218 226
219 pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { 227 pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantDef> {
220 self.imp.resolve_variant(record_lit) 228 self.imp.resolve_variant(record_lit).map(VariantDef::from)
221 } 229 }
222 230
223 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { 231 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> {
@@ -266,17 +274,17 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
266} 274}
267 275
268impl<'db> SemanticsImpl<'db> { 276impl<'db> SemanticsImpl<'db> {
269 pub fn new(db: &'db dyn HirDatabase) -> Self { 277 fn new(db: &'db dyn HirDatabase) -> Self {
270 Self { db, s2d_cache: Default::default(), cache: Default::default() } 278 Self { db, s2d_cache: Default::default(), cache: Default::default() }
271 } 279 }
272 280
273 pub fn parse(&self, file_id: FileId) -> ast::SourceFile { 281 fn parse(&self, file_id: FileId) -> ast::SourceFile {
274 let tree = self.db.parse(file_id).tree(); 282 let tree = self.db.parse(file_id).tree();
275 self.cache(tree.syntax().clone(), file_id.into()); 283 self.cache(tree.syntax().clone(), file_id.into());
276 tree 284 tree
277 } 285 }
278 286
279 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { 287 fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
280 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); 288 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call);
281 let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); 289 let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
282 let file_id = sa.expand(self.db, macro_call)?; 290 let file_id = sa.expand(self.db, macro_call)?;
@@ -285,7 +293,7 @@ impl<'db> SemanticsImpl<'db> {
285 Some(node) 293 Some(node)
286 } 294 }
287 295
288 pub fn expand_hypothetical( 296 fn expand_hypothetical(
289 &self, 297 &self,
290 actual_macro_call: &ast::MacroCall, 298 actual_macro_call: &ast::MacroCall,
291 hypothetical_args: &ast::TokenTree, 299 hypothetical_args: &ast::TokenTree,
@@ -306,7 +314,7 @@ impl<'db> SemanticsImpl<'db> {
306 ) 314 )
307 } 315 }
308 316
309 pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken { 317 fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
310 let parent = token.parent(); 318 let parent = token.parent();
311 let parent = self.find_file(parent); 319 let parent = self.find_file(parent);
312 let sa = self.analyze2(parent.as_ref(), None); 320 let sa = self.analyze2(parent.as_ref(), None);
@@ -330,7 +338,7 @@ impl<'db> SemanticsImpl<'db> {
330 token.value 338 token.value
331 } 339 }
332 340
333 pub fn descend_node_at_offset( 341 fn descend_node_at_offset(
334 &self, 342 &self,
335 node: &SyntaxNode, 343 node: &SyntaxNode,
336 offset: TextSize, 344 offset: TextSize,
@@ -342,24 +350,24 @@ impl<'db> SemanticsImpl<'db> {
342 .flatten() 350 .flatten()
343 } 351 }
344 352
345 pub fn original_range(&self, node: &SyntaxNode) -> FileRange { 353 fn original_range(&self, node: &SyntaxNode) -> FileRange {
346 let node = self.find_file(node.clone()); 354 let node = self.find_file(node.clone());
347 original_range(self.db, node.as_ref()) 355 original_range(self.db, node.as_ref())
348 } 356 }
349 357
350 pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { 358 fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange {
351 let src = diagnostics.source(); 359 let src = diagnostics.source();
352 let root = self.db.parse_or_expand(src.file_id).unwrap(); 360 let root = self.db.parse_or_expand(src.file_id).unwrap();
353 let node = src.value.to_node(&root); 361 let node = src.value.to_node(&root);
354 original_range(self.db, src.with_value(&node)) 362 original_range(self.db, src.with_value(&node))
355 } 363 }
356 364
357 pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { 365 fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
358 let node = self.find_file(node); 366 let node = self.find_file(node);
359 node.ancestors_with_macros(self.db.upcast()).map(|it| it.value) 367 node.ancestors_with_macros(self.db.upcast()).map(|it| it.value)
360 } 368 }
361 369
362 pub fn ancestors_at_offset_with_macros( 370 fn ancestors_at_offset_with_macros(
363 &self, 371 &self,
364 node: &SyntaxNode, 372 node: &SyntaxNode,
365 offset: TextSize, 373 offset: TextSize,
@@ -369,60 +377,75 @@ impl<'db> SemanticsImpl<'db> {
369 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) 377 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
370 } 378 }
371 379
372 pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { 380 fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
373 self.analyze(expr.syntax()).type_of(self.db, &expr) 381 self.analyze(expr.syntax()).type_of_expr(self.db, &expr)
374 } 382 }
375 383
376 pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { 384 fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
377 self.analyze(pat.syntax()).type_of_pat(self.db, &pat) 385 self.analyze(pat.syntax()).type_of_pat(self.db, &pat)
378 } 386 }
379 387
380 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 388 fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
389 self.analyze(param.syntax()).type_of_self(self.db, &param)
390 }
391
392 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
381 self.analyze(call.syntax()).resolve_method_call(self.db, call) 393 self.analyze(call.syntax()).resolve_method_call(self.db, call)
382 } 394 }
383 395
384 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { 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
407 fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
385 self.analyze(field.syntax()).resolve_field(self.db, field) 408 self.analyze(field.syntax()).resolve_field(self.db, field)
386 } 409 }
387 410
388 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> { 411 fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> {
389 self.analyze(field.syntax()).resolve_record_field(self.db, field) 412 self.analyze(field.syntax()).resolve_record_field(self.db, field)
390 } 413 }
391 414
392 pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { 415 fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> {
393 self.analyze(field.syntax()).resolve_record_field_pat(self.db, field) 416 self.analyze(field.syntax()).resolve_record_field_pat(self.db, field)
394 } 417 }
395 418
396 pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { 419 fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> {
397 let sa = self.analyze(macro_call.syntax()); 420 let sa = self.analyze(macro_call.syntax());
398 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); 421 let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call);
399 sa.resolve_macro_call(self.db, macro_call) 422 sa.resolve_macro_call(self.db, macro_call)
400 } 423 }
401 424
402 pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { 425 fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
403 self.analyze(path.syntax()).resolve_path(self.db, path) 426 self.analyze(path.syntax()).resolve_path(self.db, path)
404 } 427 }
405 428
406 pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> { 429 fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> {
407 self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) 430 self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit)
408 } 431 }
409 432
410 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> { 433 fn lower_path(&self, path: &ast::Path) -> Option<Path> {
411 let src = self.find_file(path.syntax().clone()); 434 let src = self.find_file(path.syntax().clone());
412 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into())) 435 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into()))
413 } 436 }
414 437
415 pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { 438 fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> {
416 self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) 439 self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
417 } 440 }
418 441
419 pub fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> { 442 fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> {
420 self.analyze(literal.syntax()) 443 self.analyze(literal.syntax())
421 .record_literal_missing_fields(self.db, literal) 444 .record_literal_missing_fields(self.db, literal)
422 .unwrap_or_default() 445 .unwrap_or_default()
423 } 446 }
424 447
425 pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { 448 fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> {
426 self.analyze(pattern.syntax()) 449 self.analyze(pattern.syntax())
427 .record_pattern_missing_fields(self.db, pattern) 450 .record_pattern_missing_fields(self.db, pattern)
428 .unwrap_or_default() 451 .unwrap_or_default()
@@ -434,23 +457,23 @@ impl<'db> SemanticsImpl<'db> {
434 f(&mut ctx) 457 f(&mut ctx)
435 } 458 }
436 459
437 pub fn to_module_def(&self, file: FileId) -> Option<Module> { 460 fn to_module_def(&self, file: FileId) -> Option<Module> {
438 self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from) 461 self.with_ctx(|ctx| ctx.file_to_def(file)).map(Module::from)
439 } 462 }
440 463
441 pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { 464 fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
442 let node = self.find_file(node.clone()); 465 let node = self.find_file(node.clone());
443 let resolver = self.analyze2(node.as_ref(), None).resolver; 466 let resolver = self.analyze2(node.as_ref(), None).resolver;
444 SemanticsScope { db: self.db, resolver } 467 SemanticsScope { db: self.db, resolver }
445 } 468 }
446 469
447 pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { 470 fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
448 let node = self.find_file(node.clone()); 471 let node = self.find_file(node.clone());
449 let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver; 472 let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver;
450 SemanticsScope { db: self.db, resolver } 473 SemanticsScope { db: self.db, resolver }
451 } 474 }
452 475
453 pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { 476 fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
454 let resolver = def.id.resolver(self.db.upcast()); 477 let resolver = def.id.resolver(self.db.upcast());
455 SemanticsScope { db: self.db, resolver } 478 SemanticsScope { db: self.db, resolver }
456 } 479 }
@@ -477,19 +500,20 @@ impl<'db> SemanticsImpl<'db> {
477 ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()), 500 ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()),
478 ChildContainer::EnumId(it) => it.resolver(self.db.upcast()), 501 ChildContainer::EnumId(it) => it.resolver(self.db.upcast()),
479 ChildContainer::VariantId(it) => it.resolver(self.db.upcast()), 502 ChildContainer::VariantId(it) => it.resolver(self.db.upcast()),
503 ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()),
480 ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()), 504 ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()),
481 }; 505 };
482 SourceAnalyzer::new_for_resolver(resolver, src) 506 SourceAnalyzer::new_for_resolver(resolver, src)
483 } 507 }
484 508
485 pub fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) { 509 fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
486 assert!(root_node.parent().is_none()); 510 assert!(root_node.parent().is_none());
487 let mut cache = self.cache.borrow_mut(); 511 let mut cache = self.cache.borrow_mut();
488 let prev = cache.insert(root_node, file_id); 512 let prev = cache.insert(root_node, file_id);
489 assert!(prev == None || prev == Some(file_id)) 513 assert!(prev == None || prev == Some(file_id))
490 } 514 }
491 515
492 pub fn assert_contains_node(&self, node: &SyntaxNode) { 516 fn assert_contains_node(&self, node: &SyntaxNode) {
493 self.find_file(node.clone()); 517 self.find_file(node.clone());
494 } 518 }
495 519
@@ -498,7 +522,7 @@ impl<'db> SemanticsImpl<'db> {
498 cache.get(root_node).copied() 522 cache.get(root_node).copied()
499 } 523 }
500 524
501 pub fn find_file(&self, node: SyntaxNode) -> InFile<SyntaxNode> { 525 fn find_file(&self, node: SyntaxNode) -> InFile<SyntaxNode> {
502 let root_node = find_root(&node); 526 let root_node = find_root(&node);
503 let file_id = self.lookup(&root_node).unwrap_or_else(|| { 527 let file_id = self.lookup(&root_node).unwrap_or_else(|| {
504 panic!( 528 panic!(
@@ -560,6 +584,7 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode {
560 node.ancestors().last().unwrap() 584 node.ancestors().last().unwrap()
561} 585}
562 586
587#[derive(Debug)]
563pub struct SemanticsScope<'a> { 588pub struct SemanticsScope<'a> {
564 pub db: &'a dyn HirDatabase, 589 pub db: &'a dyn HirDatabase,
565 resolver: Resolver, 590 resolver: Resolver,
diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs
index 8af64fdc1..42e5a1bdb 100644
--- a/crates/ra_hir/src/semantics/source_to_def.rs
+++ b/crates/ra_hir/src/semantics/source_to_def.rs
@@ -16,6 +16,7 @@ use ra_syntax::{
16 match_ast, AstNode, SyntaxNode, 16 match_ast, AstNode, SyntaxNode,
17}; 17};
18use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
19use stdx::impl_from;
19 20
20use crate::{db::HirDatabase, InFile, MacroDefId}; 21use crate::{db::HirDatabase, InFile, MacroDefId};
21 22
@@ -194,6 +195,10 @@ impl SourceToDefCtx<'_, '_> {
194 let def = self.const_to_def(container.with_value(it))?; 195 let def = self.const_to_def(container.with_value(it))?;
195 DefWithBodyId::from(def).into() 196 DefWithBodyId::from(def).into()
196 }, 197 },
198 ast::TypeAliasDef(it) => {
199 let def = self.type_alias_to_def(container.with_value(it))?;
200 def.into()
201 },
197 _ => continue, 202 _ => continue,
198 } 203 }
199 }; 204 };
@@ -246,19 +251,21 @@ pub(crate) enum ChildContainer {
246 ImplId(ImplId), 251 ImplId(ImplId),
247 EnumId(EnumId), 252 EnumId(EnumId),
248 VariantId(VariantId), 253 VariantId(VariantId),
254 TypeAliasId(TypeAliasId),
249 /// XXX: this might be the same def as, for example an `EnumId`. However, 255 /// XXX: this might be the same def as, for example an `EnumId`. However,
250 /// here the children generic parameters, and not, eg enum variants. 256 /// here the children generic parameters, and not, eg enum variants.
251 GenericDefId(GenericDefId), 257 GenericDefId(GenericDefId),
252} 258}
253impl_froms! { 259impl_from! {
254 ChildContainer:
255 DefWithBodyId, 260 DefWithBodyId,
256 ModuleId, 261 ModuleId,
257 TraitId, 262 TraitId,
258 ImplId, 263 ImplId,
259 EnumId, 264 EnumId,
260 VariantId, 265 VariantId,
266 TypeAliasId,
261 GenericDefId 267 GenericDefId
268 for ChildContainer
262} 269}
263 270
264impl ChildContainer { 271impl ChildContainer {
@@ -271,6 +278,7 @@ impl ChildContainer {
271 ChildContainer::ImplId(it) => it.child_by_source(db), 278 ChildContainer::ImplId(it) => it.child_by_source(db),
272 ChildContainer::EnumId(it) => it.child_by_source(db), 279 ChildContainer::EnumId(it) => it.child_by_source(db),
273 ChildContainer::VariantId(it) => it.child_by_source(db), 280 ChildContainer::VariantId(it) => it.child_by_source(db),
281 ChildContainer::TypeAliasId(_) => DynMap::default(),
274 ChildContainer::GenericDefId(it) => it.child_by_source(db), 282 ChildContainer::GenericDefId(it) => it.child_by_source(db),
275 } 283 }
276 } 284 }
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 1d6c47103..86a47a9e5 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -14,11 +14,11 @@ 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::{
21 expr::{record_literal_missing_fields, record_pattern_missing_fields}, 21 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
22 InferenceResult, Substs, Ty, 22 InferenceResult, Substs, Ty,
23}; 23};
24use ra_syntax::{ 24use ra_syntax::{
@@ -115,7 +115,7 @@ impl SourceAnalyzer {
115 Some(res) 115 Some(res)
116 } 116 }
117 117
118 pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { 118 pub(crate) fn type_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> {
119 let expr_id = self.expr_id(db, expr)?; 119 let expr_id = self.expr_id(db, expr)?;
120 let ty = self.infer.as_ref()?[expr_id].clone(); 120 let ty = self.infer.as_ref()?[expr_id].clone();
121 Type::new_with_resolver(db, &self.resolver, ty) 121 Type::new_with_resolver(db, &self.resolver, ty)
@@ -127,13 +127,24 @@ impl SourceAnalyzer {
127 Type::new_with_resolver(db, &self.resolver, ty) 127 Type::new_with_resolver(db, &self.resolver, ty)
128 } 128 }
129 129
130 pub(crate) fn type_of_self(
131 &self,
132 db: &dyn HirDatabase,
133 param: &ast::SelfParam,
134 ) -> Option<Type> {
135 let src = InFile { file_id: self.file_id, value: param };
136 let pat_id = self.body_source_map.as_ref()?.node_self_param(src)?;
137 let ty = self.infer.as_ref()?[pat_id].clone();
138 Type::new_with_resolver(db, &self.resolver, ty)
139 }
140
130 pub(crate) fn resolve_method_call( 141 pub(crate) fn resolve_method_call(
131 &self, 142 &self,
132 db: &dyn HirDatabase, 143 db: &dyn HirDatabase,
133 call: &ast::MethodCallExpr, 144 call: &ast::MethodCallExpr,
134 ) -> Option<Function> { 145 ) -> Option<FunctionId> {
135 let expr_id = self.expr_id(db, &call.clone().into())?; 146 let expr_id = self.expr_id(db, &call.clone().into())?;
136 self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) 147 self.infer.as_ref()?.method_resolution(expr_id)
137 } 148 }
138 149
139 pub(crate) fn resolve_field( 150 pub(crate) fn resolve_field(
@@ -341,7 +352,7 @@ impl SourceAnalyzer {
341 let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { 352 let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
342 self.resolver.resolve_path_as_macro(db.upcast(), &path) 353 self.resolver.resolve_path_as_macro(db.upcast(), &path)
343 })?; 354 })?;
344 Some(macro_call_id.as_file()) 355 Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64)
345 } 356 }
346 357
347 pub(crate) fn resolve_variant( 358 pub(crate) fn resolve_variant(