aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/Cargo.toml7
-rw-r--r--crates/ra_hir/src/adt.rs180
-rw-r--r--crates/ra_hir/src/code_model.rs124
-rw-r--r--crates/ra_hir/src/code_model/src.rs48
-rw-r--r--crates/ra_hir/src/db.rs19
-rw-r--r--crates/ra_hir/src/diagnostics.rs102
-rw-r--r--crates/ra_hir/src/expr/validation.rs3
-rw-r--r--crates/ra_hir/src/from_id.rs63
-rw-r--r--crates/ra_hir/src/from_source.rs22
-rw-r--r--crates/ra_hir/src/generics.rs3
-rw-r--r--crates/ra_hir/src/lib.rs18
-rw-r--r--crates/ra_hir/src/mock.rs6
-rw-r--r--crates/ra_hir/src/nameres.rs559
-rw-r--r--crates/ra_hir/src/nameres/collector.rs834
-rw-r--r--crates/ra_hir/src/nameres/mod_resolution.rs80
-rw-r--r--crates/ra_hir/src/nameres/per_ns.rs80
-rw-r--r--crates/ra_hir/src/nameres/tests.rs578
-rw-r--r--crates/ra_hir/src/nameres/tests/globs.rs118
-rw-r--r--crates/ra_hir/src/nameres/tests/incremental.rs141
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs635
-rw-r--r--crates/ra_hir/src/nameres/tests/mod_resolution.rs759
-rw-r--r--crates/ra_hir/src/nameres/tests/primitives.rs24
-rw-r--r--crates/ra_hir/src/resolve.rs112
-rw-r--r--crates/ra_hir/src/source_binder.rs111
-rw-r--r--crates/ra_hir/src/ty.rs19
-rw-r--r--crates/ra_hir/src/ty/infer.rs12
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs3
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs82
-rw-r--r--crates/ra_hir/src/ty/lower.rs23
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs141
-rw-r--r--crates/ra_hir/src/ty/primitive.rs22
-rw-r--r--crates/ra_hir/src/ty/tests.rs175
32 files changed, 692 insertions, 4411 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 5df371bc0..324961328 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -7,7 +7,6 @@ authors = ["rust-analyzer developers"]
7[dependencies] 7[dependencies]
8arrayvec = "0.5.1" 8arrayvec = "0.5.1"
9log = "0.4.5" 9log = "0.4.5"
10relative-path = "1.0.0"
11rustc-hash = "1.0" 10rustc-hash = "1.0"
12parking_lot = "0.9.0" 11parking_lot = "0.9.0"
13ena = "0.13" 12ena = "0.13"
@@ -24,9 +23,9 @@ hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
24test_utils = { path = "../test_utils" } 23test_utils = { path = "../test_utils" }
25ra_prof = { path = "../ra_prof" } 24ra_prof = { path = "../ra_prof" }
26 25
27chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "8314f2fcec8582a58c24b638f1a259d4145a0809" } 26chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "50f9f636123bd88d0cc1b958749981d6702e4d05" }
28chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "8314f2fcec8582a58c24b638f1a259d4145a0809" } 27chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "50f9f636123bd88d0cc1b958749981d6702e4d05" }
29chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "8314f2fcec8582a58c24b638f1a259d4145a0809" } 28chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "50f9f636123bd88d0cc1b958749981d6702e4d05" }
30lalrpop-intern = "0.15.1" 29lalrpop-intern = "0.15.1"
31 30
32[dev-dependencies] 31[dev-dependencies]
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 97424b39e..0436d20b7 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -3,156 +3,16 @@
3 3
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::type_ref::TypeRef; 6use hir_def::adt::VariantData;
7use hir_expand::name::AsName;
8use ra_arena::{impl_arena_id, Arena, RawId};
9use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner};
10 7
11use crate::{ 8use crate::{
12 db::{AstDatabase, DefDatabase, HirDatabase}, 9 db::{DefDatabase, HirDatabase},
13 Enum, EnumVariant, FieldSource, HasSource, Module, Name, Source, Struct, StructField, 10 EnumVariant, Module, Name, Struct, StructField,
14}; 11};
15 12
16impl Struct { 13impl Struct {
17 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 14 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
18 db.struct_data(self).variant_data.clone() 15 db.struct_data(self.id).variant_data.clone()
19 }
20}
21
22/// Note that we use `StructData` for unions as well!
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct StructData {
25 pub(crate) name: Option<Name>,
26 pub(crate) variant_data: Arc<VariantData>,
27}
28
29impl StructData {
30 fn new(struct_def: &ast::StructDef) -> StructData {
31 let name = struct_def.name().map(|n| n.as_name());
32 let variant_data = VariantData::new(struct_def.kind());
33 let variant_data = Arc::new(variant_data);
34 StructData { name, variant_data }
35 }
36
37 pub(crate) fn struct_data_query(
38 db: &(impl DefDatabase + AstDatabase),
39 struct_: Struct,
40 ) -> Arc<StructData> {
41 let src = struct_.source(db);
42 Arc::new(StructData::new(&src.ast))
43 }
44}
45
46fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = ast::EnumVariant> {
47 enum_def.variant_list().into_iter().flat_map(|it| it.variants())
48}
49
50impl EnumVariant {
51 pub(crate) fn source_impl(
52 self,
53 db: &(impl DefDatabase + AstDatabase),
54 ) -> Source<ast::EnumVariant> {
55 let src = self.parent.source(db);
56 let ast = variants(&src.ast)
57 .zip(db.enum_data(self.parent).variants.iter())
58 .find(|(_syntax, (id, _))| *id == self.id)
59 .unwrap()
60 .0;
61 Source { file_id: src.file_id, ast }
62 }
63 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
64 db.enum_data(self.parent).variants[self.id].variant_data.clone()
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct EnumData {
70 pub(crate) name: Option<Name>,
71 pub(crate) variants: Arena<EnumVariantId, EnumVariantData>,
72}
73
74impl EnumData {
75 pub(crate) fn enum_data_query(db: &(impl DefDatabase + AstDatabase), e: Enum) -> Arc<EnumData> {
76 let src = e.source(db);
77 let name = src.ast.name().map(|n| n.as_name());
78 let variants = variants(&src.ast)
79 .map(|var| EnumVariantData {
80 name: var.name().map(|it| it.as_name()),
81 variant_data: Arc::new(VariantData::new(var.kind())),
82 })
83 .collect();
84 Arc::new(EnumData { name, variants })
85 }
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
89pub(crate) struct EnumVariantId(RawId);
90impl_arena_id!(EnumVariantId);
91
92#[derive(Debug, Clone, PartialEq, Eq)]
93pub(crate) struct EnumVariantData {
94 pub(crate) name: Option<Name>,
95 variant_data: Arc<VariantData>,
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
99pub(crate) struct StructFieldId(RawId);
100impl_arena_id!(StructFieldId);
101
102/// A single field of an enum variant or struct
103#[derive(Debug, Clone, PartialEq, Eq)]
104pub struct StructFieldData {
105 pub(crate) name: Name,
106 pub(crate) type_ref: TypeRef,
107}
108
109/// Fields of an enum variant or struct
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub(crate) struct VariantData(VariantDataInner);
112
113#[derive(Debug, Clone, PartialEq, Eq)]
114enum VariantDataInner {
115 Struct(Arena<StructFieldId, StructFieldData>),
116 Tuple(Arena<StructFieldId, StructFieldData>),
117 Unit,
118}
119
120impl VariantData {
121 pub(crate) fn fields(&self) -> Option<&Arena<StructFieldId, StructFieldData>> {
122 match &self.0 {
123 VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
124 _ => None,
125 }
126 }
127}
128
129impl VariantData {
130 fn new(flavor: StructKind) -> Self {
131 let inner = match flavor {
132 ast::StructKind::Tuple(fl) => {
133 let fields = fl
134 .fields()
135 .enumerate()
136 .map(|(i, fd)| StructFieldData {
137 name: Name::new_tuple_field(i),
138 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
139 })
140 .collect();
141 VariantDataInner::Tuple(fields)
142 }
143 ast::StructKind::Named(fl) => {
144 let fields = fl
145 .fields()
146 .map(|fd| StructFieldData {
147 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
148 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
149 })
150 .collect();
151 VariantDataInner::Struct(fields)
152 }
153 ast::StructKind::Unit => VariantDataInner::Unit,
154 };
155 VariantData(inner)
156 } 16 }
157} 17}
158 18
@@ -192,35 +52,3 @@ impl VariantDef {
192 } 52 }
193 } 53 }
194} 54}
195
196impl StructField {
197 pub(crate) fn source_impl(&self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
198 let var_data = self.parent.variant_data(db);
199 let fields = var_data.fields().unwrap();
200 let ss;
201 let es;
202 let (file_id, struct_kind) = match self.parent {
203 VariantDef::Struct(s) => {
204 ss = s.source(db);
205 (ss.file_id, ss.ast.kind())
206 }
207 VariantDef::EnumVariant(e) => {
208 es = e.source(db);
209 (es.file_id, es.ast.kind())
210 }
211 };
212
213 let field_sources = match struct_kind {
214 ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
215 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
216 ast::StructKind::Unit => Vec::new(),
217 };
218 let ast = field_sources
219 .into_iter()
220 .zip(fields.iter())
221 .find(|(_syntax, (id, _))| *id == self.id)
222 .unwrap()
223 .0;
224 Source { file_id, ast }
225 }
226}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index a6ce23dd1..181c5d47a 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -6,20 +6,21 @@ pub(crate) mod docs;
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use hir_def::{ 8use hir_def::{
9 adt::VariantData,
10 builtin_type::BuiltinType,
9 type_ref::{Mutability, TypeRef}, 11 type_ref::{Mutability, TypeRef},
10 CrateModuleId, ModuleId, 12 CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId,
11}; 13};
12use hir_expand::name::{ 14use hir_expand::{
13 self, AsName, BOOL, CHAR, F32, F64, I128, I16, I32, I64, I8, ISIZE, SELF_TYPE, STR, U128, U16, 15 diagnostics::DiagnosticSink,
14 U32, U64, U8, USIZE, 16 name::{self, AsName},
15}; 17};
16use ra_db::{CrateId, Edition}; 18use ra_db::{CrateId, Edition};
17use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 19use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
18 20
19use crate::{ 21use crate::{
20 adt::{EnumVariantId, StructFieldId, VariantDef}, 22 adt::VariantDef,
21 db::{AstDatabase, DefDatabase, HirDatabase}, 23 db::{AstDatabase, DefDatabase, HirDatabase},
22 diagnostics::DiagnosticSink,
23 expr::{validation::ExprValidator, Body, BodySourceMap}, 24 expr::{validation::ExprValidator, Body, BodySourceMap},
24 generics::HasGenericParams, 25 generics::HasGenericParams,
25 ids::{ 26 ids::{
@@ -27,14 +28,10 @@ use crate::{
27 TypeAliasId, 28 TypeAliasId,
28 }, 29 },
29 impl_block::ImplBlock, 30 impl_block::ImplBlock,
30 nameres::{ImportId, ModuleScope, Namespace},
31 resolve::{Resolver, Scope, TypeNs}, 31 resolve::{Resolver, Scope, TypeNs},
32 traits::TraitData, 32 traits::TraitData,
33 ty::{ 33 ty::{InferenceResult, TraitRef},
34 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, 34 Either, HasSource, Name, ScopeDef, Ty, {ImportId, Namespace},
35 InferenceResult, TraitRef,
36 },
37 Either, HasSource, Name, Ty,
38}; 35};
39 36
40/// hir::Crate describes a single crate. It's the main interface with which 37/// hir::Crate describes a single crate. It's the main interface with which
@@ -68,7 +65,7 @@ impl Crate {
68 } 65 }
69 66
70 pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> { 67 pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> {
71 let module_id = db.crate_def_map(self).root(); 68 let module_id = db.crate_def_map(self.crate_id).root();
72 Some(Module::new(self, module_id)) 69 Some(Module::new(self, module_id))
73 } 70 }
74 71
@@ -87,41 +84,6 @@ pub struct Module {
87 pub(crate) id: ModuleId, 84 pub(crate) id: ModuleId,
88} 85}
89 86
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
91pub enum BuiltinType {
92 Char,
93 Bool,
94 Str,
95 Int(IntTy),
96 Float(FloatTy),
97}
98
99impl BuiltinType {
100 #[rustfmt::skip]
101 pub(crate) const ALL: &'static [(Name, BuiltinType)] = &[
102 (CHAR, BuiltinType::Char),
103 (BOOL, BuiltinType::Bool),
104 (STR, BuiltinType::Str),
105
106 (ISIZE, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::Xsize })),
107 (I8, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X8 })),
108 (I16, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X16 })),
109 (I32, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X32 })),
110 (I64, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X64 })),
111 (I128, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X128 })),
112
113 (USIZE, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize })),
114 (U8, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X8 })),
115 (U16, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X16 })),
116 (U32, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X32 })),
117 (U64, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X64 })),
118 (U128, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 })),
119
120 (F32, BuiltinType::Float(FloatTy { bitness: FloatBitness::X32 })),
121 (F64, BuiltinType::Float(FloatTy { bitness: FloatBitness::X64 })),
122 ];
123}
124
125/// The defs which can be visible in the module. 87/// The defs which can be visible in the module.
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
127pub enum ModuleDef { 89pub enum ModuleDef {
@@ -157,7 +119,7 @@ impl Module {
157 119
158 /// Name of this module. 120 /// Name of this module.
159 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 121 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
160 let def_map = db.crate_def_map(self.krate()); 122 let def_map = db.crate_def_map(self.id.krate);
161 let parent = def_map[self.id.module_id].parent?; 123 let parent = def_map[self.id.module_id].parent?;
162 def_map[parent].children.iter().find_map(|(name, module_id)| { 124 def_map[parent].children.iter().find_map(|(name, module_id)| {
163 if *module_id == self.id.module_id { 125 if *module_id == self.id.module_id {
@@ -188,20 +150,20 @@ impl Module {
188 /// might be missing `krate`. This can happen if a module's file is not included 150 /// might be missing `krate`. This can happen if a module's file is not included
189 /// in the module tree of any target in `Cargo.toml`. 151 /// in the module tree of any target in `Cargo.toml`.
190 pub fn crate_root(self, db: &impl DefDatabase) -> Module { 152 pub fn crate_root(self, db: &impl DefDatabase) -> Module {
191 let def_map = db.crate_def_map(self.krate()); 153 let def_map = db.crate_def_map(self.id.krate);
192 self.with_module_id(def_map.root()) 154 self.with_module_id(def_map.root())
193 } 155 }
194 156
195 /// Finds a child module with the specified name. 157 /// Finds a child module with the specified name.
196 pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> { 158 pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
197 let def_map = db.crate_def_map(self.krate()); 159 let def_map = db.crate_def_map(self.id.krate);
198 let child_id = def_map[self.id.module_id].children.get(name)?; 160 let child_id = def_map[self.id.module_id].children.get(name)?;
199 Some(self.with_module_id(*child_id)) 161 Some(self.with_module_id(*child_id))
200 } 162 }
201 163
202 /// Iterates over all child modules. 164 /// Iterates over all child modules.
203 pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> { 165 pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> {
204 let def_map = db.crate_def_map(self.krate()); 166 let def_map = db.crate_def_map(self.id.krate);
205 let children = def_map[self.id.module_id] 167 let children = def_map[self.id.module_id]
206 .children 168 .children
207 .iter() 169 .iter()
@@ -212,7 +174,7 @@ impl Module {
212 174
213 /// Finds a parent module. 175 /// Finds a parent module.
214 pub fn parent(self, db: &impl DefDatabase) -> Option<Module> { 176 pub fn parent(self, db: &impl DefDatabase) -> Option<Module> {
215 let def_map = db.crate_def_map(self.krate()); 177 let def_map = db.crate_def_map(self.id.krate);
216 let parent_id = def_map[self.id.module_id].parent?; 178 let parent_id = def_map[self.id.module_id].parent?;
217 Some(self.with_module_id(parent_id)) 179 Some(self.with_module_id(parent_id))
218 } 180 }
@@ -228,12 +190,16 @@ impl Module {
228 } 190 }
229 191
230 /// Returns a `ModuleScope`: a set of items, visible in this module. 192 /// Returns a `ModuleScope`: a set of items, visible in this module.
231 pub fn scope(self, db: &impl HirDatabase) -> ModuleScope { 193 pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<ImportId>)> {
232 db.crate_def_map(self.krate())[self.id.module_id].scope.clone() 194 db.crate_def_map(self.id.krate)[self.id.module_id]
195 .scope
196 .entries()
197 .map(|(name, res)| (name.clone(), res.def.into(), res.import))
198 .collect()
233 } 199 }
234 200
235 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { 201 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
236 db.crate_def_map(self.krate()).add_diagnostics(db, self.id.module_id, sink); 202 db.crate_def_map(self.id.krate).add_diagnostics(db, self.id.module_id, sink);
237 for decl in self.declarations(db) { 203 for decl in self.declarations(db) {
238 match decl { 204 match decl {
239 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 205 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
@@ -257,12 +223,12 @@ impl Module {
257 } 223 }
258 224
259 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { 225 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
260 let def_map = db.crate_def_map(self.krate()); 226 let def_map = db.crate_def_map(self.id.krate);
261 Resolver::default().push_module_scope(def_map, self.id.module_id) 227 Resolver::default().push_module_scope(def_map, self.id.module_id)
262 } 228 }
263 229
264 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> { 230 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
265 let def_map = db.crate_def_map(self.krate()); 231 let def_map = db.crate_def_map(self.id.krate);
266 def_map[self.id.module_id] 232 def_map[self.id.module_id]
267 .scope 233 .scope
268 .entries() 234 .entries()
@@ -270,6 +236,7 @@ impl Module {
270 .flat_map(|per_ns| { 236 .flat_map(|per_ns| {
271 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) 237 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
272 }) 238 })
239 .map(ModuleDef::from)
273 .collect() 240 .collect()
274 } 241 }
275 242
@@ -290,7 +257,7 @@ impl Module {
290#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 257#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
291pub struct StructField { 258pub struct StructField {
292 pub(crate) parent: VariantDef, 259 pub(crate) parent: VariantDef,
293 pub(crate) id: StructFieldId, 260 pub(crate) id: LocalStructFieldId,
294} 261}
295 262
296#[derive(Debug, PartialEq, Eq)] 263#[derive(Debug, PartialEq, Eq)]
@@ -328,11 +295,11 @@ impl Struct {
328 } 295 }
329 296
330 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 297 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
331 db.struct_data(self).name.clone() 298 db.struct_data(self.id).name.clone()
332 } 299 }
333 300
334 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 301 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
335 db.struct_data(self) 302 db.struct_data(self.id)
336 .variant_data 303 .variant_data
337 .fields() 304 .fields()
338 .into_iter() 305 .into_iter()
@@ -342,7 +309,7 @@ impl Struct {
342 } 309 }
343 310
344 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { 311 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
345 db.struct_data(self) 312 db.struct_data(self.id)
346 .variant_data 313 .variant_data
347 .fields() 314 .fields()
348 .into_iter() 315 .into_iter()
@@ -373,12 +340,12 @@ impl Struct {
373 340
374#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 341#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
375pub struct Union { 342pub struct Union {
376 pub(crate) id: StructId, 343 pub(crate) id: UnionId,
377} 344}
378 345
379impl Union { 346impl Union {
380 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 347 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
381 db.struct_data(Struct { id: self.id }).name.clone() 348 db.union_data(self.id).name.clone()
382 } 349 }
383 350
384 pub fn module(self, db: &impl HirDatabase) -> Module { 351 pub fn module(self, db: &impl HirDatabase) -> Module {
@@ -416,15 +383,19 @@ impl Enum {
416 } 383 }
417 384
418 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 385 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
419 db.enum_data(self).name.clone() 386 db.enum_data(self.id).name.clone()
420 } 387 }
421 388
422 pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> { 389 pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> {
423 db.enum_data(self).variants.iter().map(|(id, _)| EnumVariant { parent: self, id }).collect() 390 db.enum_data(self.id)
391 .variants
392 .iter()
393 .map(|(id, _)| EnumVariant { parent: self, id })
394 .collect()
424 } 395 }
425 396
426 pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> { 397 pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> {
427 db.enum_data(self) 398 db.enum_data(self.id)
428 .variants 399 .variants
429 .iter() 400 .iter()
430 .find(|(_id, data)| data.name.as_ref() == Some(name)) 401 .find(|(_id, data)| data.name.as_ref() == Some(name))
@@ -450,7 +421,7 @@ impl Enum {
450#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 421#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
451pub struct EnumVariant { 422pub struct EnumVariant {
452 pub(crate) parent: Enum, 423 pub(crate) parent: Enum,
453 pub(crate) id: EnumVariantId, 424 pub(crate) id: LocalEnumVariantId,
454} 425}
455 426
456impl EnumVariant { 427impl EnumVariant {
@@ -462,7 +433,7 @@ impl EnumVariant {
462 } 433 }
463 434
464 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 435 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
465 db.enum_data(self.parent).variants[self.id].name.clone() 436 db.enum_data(self.parent.id).variants[self.id].name.clone()
466 } 437 }
467 438
468 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 439 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
@@ -482,6 +453,10 @@ impl EnumVariant {
482 .find(|(_id, data)| data.name == *name) 453 .find(|(_id, data)| data.name == *name)
483 .map(|(id, _)| StructField { parent: self.into(), id }) 454 .map(|(id, _)| StructField { parent: self.into(), id })
484 } 455 }
456
457 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
458 db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
459 }
485} 460}
486 461
487/// A Data Type 462/// A Data Type
@@ -625,7 +600,7 @@ impl FnData {
625 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 600 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
626 TypeRef::from_ast(type_ref) 601 TypeRef::from_ast(type_ref)
627 } else { 602 } else {
628 let self_type = TypeRef::Path(SELF_TYPE.into()); 603 let self_type = TypeRef::Path(name::SELF_TYPE.into());
629 match self_param.kind() { 604 match self_param.kind() {
630 ast::SelfParamKind::Owned => self_type, 605 ast::SelfParamKind::Owned => self_type,
631 ast::SelfParamKind::Ref => { 606 ast::SelfParamKind::Ref => {
@@ -1084,4 +1059,13 @@ impl AssocItem {
1084 AssocItem::TypeAlias(t) => t.module(db), 1059 AssocItem::TypeAlias(t) => t.module(db),
1085 } 1060 }
1086 } 1061 }
1062
1063 pub fn container(self, db: &impl DefDatabase) -> Container {
1064 match self {
1065 AssocItem::Function(f) => f.container(db),
1066 AssocItem::Const(c) => c.container(db),
1067 AssocItem::TypeAlias(t) => t.container(db),
1068 }
1069 .expect("AssocItem without container")
1070 }
1087} 1071}
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 5c7f61eef..6d116ee75 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -3,13 +3,14 @@
3use ra_syntax::ast::{self, AstNode}; 3use ra_syntax::ast::{self, AstNode};
4 4
5use crate::{ 5use crate::{
6 adt::VariantDef,
6 db::{AstDatabase, DefDatabase, HirDatabase}, 7 db::{AstDatabase, DefDatabase, HirDatabase},
7 ids::AstItemDef, 8 ids::AstItemDef,
8 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, 9 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module,
9 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, 10 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
10}; 11};
11 12
12pub use hir_def::Source; 13pub use hir_expand::Source;
13 14
14pub trait HasSource { 15pub trait HasSource {
15 type Ast; 16 type Ast;
@@ -21,7 +22,7 @@ pub trait HasSource {
21impl Module { 22impl Module {
22 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 23 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
23 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> { 24 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> {
24 let def_map = db.crate_def_map(self.krate()); 25 let def_map = db.crate_def_map(self.id.krate);
25 let decl_id = def_map[self.id.module_id].declaration; 26 let decl_id = def_map[self.id.module_id].declaration;
26 let file_id = def_map[self.id.module_id].definition; 27 let file_id = def_map[self.id.module_id].definition;
27 let ast = ModuleSource::new(db, file_id, decl_id); 28 let ast = ModuleSource::new(db, file_id, decl_id);
@@ -35,7 +36,7 @@ impl Module {
35 self, 36 self,
36 db: &(impl DefDatabase + AstDatabase), 37 db: &(impl DefDatabase + AstDatabase),
37 ) -> Option<Source<ast::Module>> { 38 ) -> Option<Source<ast::Module>> {
38 let def_map = db.crate_def_map(self.krate()); 39 let def_map = db.crate_def_map(self.id.krate);
39 let decl = def_map[self.id.module_id].declaration?; 40 let decl = def_map[self.id.module_id].declaration?;
40 let ast = decl.to_node(db); 41 let ast = decl.to_node(db);
41 Some(Source { file_id: decl.file_id(), ast }) 42 Some(Source { file_id: decl.file_id(), ast })
@@ -45,7 +46,33 @@ impl Module {
45impl HasSource for StructField { 46impl HasSource for StructField {
46 type Ast = FieldSource; 47 type Ast = FieldSource;
47 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> { 48 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
48 self.source_impl(db) 49 let var_data = self.parent.variant_data(db);
50 let fields = var_data.fields().unwrap();
51 let ss;
52 let es;
53 let (file_id, struct_kind) = match self.parent {
54 VariantDef::Struct(s) => {
55 ss = s.source(db);
56 (ss.file_id, ss.ast.kind())
57 }
58 VariantDef::EnumVariant(e) => {
59 es = e.source(db);
60 (es.file_id, es.ast.kind())
61 }
62 };
63
64 let field_sources = match struct_kind {
65 ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
66 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
67 ast::StructKind::Unit => Vec::new(),
68 };
69 let ast = field_sources
70 .into_iter()
71 .zip(fields.iter())
72 .find(|(_syntax, (id, _))| *id == self.id)
73 .unwrap()
74 .0;
75 Source { file_id, ast }
49 } 76 }
50} 77}
51impl HasSource for Struct { 78impl HasSource for Struct {
@@ -69,7 +96,18 @@ impl HasSource for Enum {
69impl HasSource for EnumVariant { 96impl HasSource for EnumVariant {
70 type Ast = ast::EnumVariant; 97 type Ast = ast::EnumVariant;
71 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> { 98 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> {
72 self.source_impl(db) 99 let enum_data = db.enum_data(self.parent.id);
100 let src = self.parent.id.source(db);
101 let ast = src
102 .ast
103 .variant_list()
104 .into_iter()
105 .flat_map(|it| it.variants())
106 .zip(enum_data.variants.iter())
107 .find(|(_syntax, (id, _))| *id == self.id)
108 .unwrap()
109 .0;
110 Source { file_id: src.file_id, ast }
73 } 111 }
74} 112}
75impl HasSource for Function { 113impl HasSource for Function {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index ebfd970eb..eb66325f7 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -6,26 +6,24 @@ use ra_db::salsa;
6use ra_syntax::SmolStr; 6use ra_syntax::SmolStr;
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData},
10 debug::HirDebugDatabase, 9 debug::HirDebugDatabase,
11 generics::{GenericDef, GenericParams}, 10 generics::{GenericDef, GenericParams},
12 ids, 11 ids,
13 impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, 12 impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks},
14 lang_item::{LangItemTarget, LangItems}, 13 lang_item::{LangItemTarget, LangItems},
15 nameres::{CrateDefMap, Namespace},
16 traits::TraitData, 14 traits::TraitData,
17 ty::{ 15 ty::{
18 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, 16 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate,
19 InferenceResult, Substs, Ty, TypableDef, TypeCtor, 17 InferenceResult, Substs, Ty, TypableDef, TypeCtor,
20 }, 18 },
21 type_alias::TypeAliasData, 19 type_alias::TypeAliasData,
22 Const, ConstData, Crate, DefWithBody, Enum, ExprScopes, FnData, Function, Module, Static, 20 Const, ConstData, Crate, DefWithBody, ExprScopes, FnData, Function, Module, Namespace, Static,
23 Struct, StructField, Trait, TypeAlias, 21 StructField, Trait, TypeAlias,
24}; 22};
25 23
26pub use hir_def::db::{ 24pub use hir_def::db::{
27 DefDatabase2, DefDatabase2Storage, InternDatabase, InternDatabaseStorage, RawItemsQuery, 25 CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, EnumDataQuery, InternDatabase,
28 RawItemsWithSourceMapQuery, 26 InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
29}; 27};
30pub use hir_expand::db::{ 28pub use hir_expand::db::{
31 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 29 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -36,21 +34,12 @@ pub use hir_expand::db::{
36#[salsa::query_group(DefDatabaseStorage)] 34#[salsa::query_group(DefDatabaseStorage)]
37#[salsa::requires(AstDatabase)] 35#[salsa::requires(AstDatabase)]
38pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { 36pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
39 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
40 fn struct_data(&self, s: Struct) -> Arc<StructData>;
41
42 #[salsa::invoke(crate::adt::EnumData::enum_data_query)]
43 fn enum_data(&self, e: Enum) -> Arc<EnumData>;
44
45 #[salsa::invoke(crate::traits::TraitData::trait_data_query)] 37 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
46 fn trait_data(&self, t: Trait) -> Arc<TraitData>; 38 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
47 39
48 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] 40 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
49 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; 41 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
50 42
51 #[salsa::invoke(CrateDefMap::crate_def_map_query)]
52 fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>;
53
54 #[salsa::invoke(ModuleImplBlocks::impls_in_module_with_source_map_query)] 43 #[salsa::invoke(ModuleImplBlocks::impls_in_module_with_source_map_query)]
55 fn impls_in_module_with_source_map( 44 fn impls_in_module_with_source_map(
56 &self, 45 &self,
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 9acdaf8ed..1751e7be3 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,82 +1,13 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::{any::Any, fmt}; 3use std::any::Any;
4
5use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, TextRange};
6use relative_path::RelativePathBuf;
7
8use crate::{db::HirDatabase, HirFileId, Name, Source};
9
10/// Diagnostic defines hir API for errors and warnings.
11///
12/// It is used as a `dyn` object, which you can downcast to a concrete
13/// diagnostic. DiagnosticSink are structured, meaning that they include rich
14/// information which can be used by IDE to create fixes. DiagnosticSink are
15/// expressed in terms of macro-expanded syntax tree nodes (so, it's a bad idea
16/// to diagnostic in a salsa value).
17///
18/// Internally, various subsystems of hir produce diagnostics specific to a
19/// subsystem (typically, an `enum`), which are safe to store in salsa but do not
20/// include source locations. Such internal diagnostic are transformed into an
21/// instance of `Diagnostic` on demand.
22pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
23 fn message(&self) -> String;
24 fn source(&self) -> Source<SyntaxNodePtr>;
25 fn highlight_range(&self) -> TextRange {
26 self.source().ast.range()
27 }
28 fn as_any(&self) -> &(dyn Any + Send + 'static);
29}
30
31pub trait AstDiagnostic {
32 type AST;
33 fn ast(&self, db: &impl HirDatabase) -> Self::AST;
34}
35 4
36impl dyn Diagnostic { 5use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
37 pub fn syntax_node(&self, db: &impl HirDatabase) -> SyntaxNode {
38 let node = db.parse_or_expand(self.source().file_id).unwrap();
39 self.source().ast.to_node(&node)
40 }
41 6
42 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> { 7use crate::{db::AstDatabase, HirFileId, Name, Source};
43 self.as_any().downcast_ref()
44 }
45}
46 8
47pub struct DiagnosticSink<'a> { 9pub use hir_def::diagnostics::UnresolvedModule;
48 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, 10pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
49 default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>,
50}
51
52impl<'a> DiagnosticSink<'a> {
53 pub fn new(cb: impl FnMut(&dyn Diagnostic) + 'a) -> DiagnosticSink<'a> {
54 DiagnosticSink { callbacks: Vec::new(), default_callback: Box::new(cb) }
55 }
56
57 pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> DiagnosticSink<'a> {
58 let cb = move |diag: &dyn Diagnostic| match diag.downcast_ref::<D>() {
59 Some(d) => {
60 cb(d);
61 Ok(())
62 }
63 None => Err(()),
64 };
65 self.callbacks.push(Box::new(cb));
66 self
67 }
68
69 pub(crate) fn push(&mut self, d: impl Diagnostic) {
70 let d: &dyn Diagnostic = &d;
71 for cb in self.callbacks.iter_mut() {
72 match cb(d) {
73 Ok(()) => return,
74 Err(()) => (),
75 }
76 }
77 (self.default_callback)(d)
78 }
79}
80 11
81#[derive(Debug)] 12#[derive(Debug)]
82pub struct NoSuchField { 13pub struct NoSuchField {
@@ -99,25 +30,6 @@ impl Diagnostic for NoSuchField {
99} 30}
100 31
101#[derive(Debug)] 32#[derive(Debug)]
102pub struct UnresolvedModule {
103 pub file: HirFileId,
104 pub decl: AstPtr<ast::Module>,
105 pub candidate: RelativePathBuf,
106}
107
108impl Diagnostic for UnresolvedModule {
109 fn message(&self) -> String {
110 "unresolved module".to_string()
111 }
112 fn source(&self) -> Source<SyntaxNodePtr> {
113 Source { file_id: self.file, ast: self.decl.into() }
114 }
115 fn as_any(&self) -> &(dyn Any + Send + 'static) {
116 self
117 }
118}
119
120#[derive(Debug)]
121pub struct MissingFields { 33pub struct MissingFields {
122 pub file: HirFileId, 34 pub file: HirFileId,
123 pub field_list: AstPtr<ast::RecordFieldList>, 35 pub field_list: AstPtr<ast::RecordFieldList>,
@@ -139,7 +51,7 @@ impl Diagnostic for MissingFields {
139impl AstDiagnostic for MissingFields { 51impl AstDiagnostic for MissingFields {
140 type AST = ast::RecordFieldList; 52 type AST = ast::RecordFieldList;
141 53
142 fn ast(&self, db: &impl HirDatabase) -> Self::AST { 54 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
143 let root = db.parse_or_expand(self.source().file_id).unwrap(); 55 let root = db.parse_or_expand(self.source().file_id).unwrap();
144 let node = self.source().ast.to_node(&root); 56 let node = self.source().ast.to_node(&root);
145 ast::RecordFieldList::cast(node).unwrap() 57 ast::RecordFieldList::cast(node).unwrap()
@@ -167,7 +79,7 @@ impl Diagnostic for MissingOkInTailExpr {
167impl AstDiagnostic for MissingOkInTailExpr { 79impl AstDiagnostic for MissingOkInTailExpr {
168 type AST = ast::Expr; 80 type AST = ast::Expr;
169 81
170 fn ast(&self, db: &impl HirDatabase) -> Self::AST { 82 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
171 let root = db.parse_or_expand(self.file).unwrap(); 83 let root = db.parse_or_expand(self.file).unwrap();
172 let node = self.source().ast.to_node(&root); 84 let node = self.source().ast.to_node(&root);
173 ast::Expr::cast(node).unwrap() 85 ast::Expr::cast(node).unwrap()
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index c685edda1..3054f1dce 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -3,12 +3,13 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::path::known; 5use hir_def::path::known;
6use hir_expand::diagnostics::DiagnosticSink;
6use ra_syntax::ast; 7use ra_syntax::ast;
7use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
8 9
9use crate::{ 10use crate::{
10 db::HirDatabase, 11 db::HirDatabase,
11 diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr}, 12 diagnostics::{MissingFields, MissingOkInTailExpr},
12 expr::AstPtr, 13 expr::AstPtr,
13 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, 14 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
14 Adt, Function, Name, Path, 15 Adt, Function, Name, Path,
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
new file mode 100644
index 000000000..089dbc908
--- /dev/null
+++ b/crates/ra_hir/src/from_id.rs
@@ -0,0 +1,63 @@
1//! Utility module for converting between hir_def ids and code_model wrappers.
2//!
3//! It's unclear if we need this long-term, but it's definitelly useful while we
4//! are splitting the hir.
5
6use hir_def::{AdtId, EnumVariantId, ModuleDefId};
7
8use crate::{Adt, EnumVariant, ModuleDef};
9
10macro_rules! from_id {
11 ($(($id:path, $ty:path)),*) => {$(
12 impl From<$id> for $ty {
13 fn from(id: $id) -> $ty {
14 $ty { id }
15 }
16 }
17 )*}
18}
19
20from_id![
21 (hir_def::ModuleId, crate::Module),
22 (hir_def::StructId, crate::Struct),
23 (hir_def::UnionId, crate::Union),
24 (hir_def::EnumId, crate::Enum),
25 (hir_def::TypeAliasId, crate::TypeAlias),
26 (hir_def::TraitId, crate::Trait),
27 (hir_def::StaticId, crate::Static),
28 (hir_def::ConstId, crate::Const),
29 (hir_def::FunctionId, crate::Function),
30 (hir_expand::MacroDefId, crate::MacroDef)
31];
32
33impl From<AdtId> for Adt {
34 fn from(id: AdtId) -> Self {
35 match id {
36 AdtId::StructId(it) => Adt::Struct(it.into()),
37 AdtId::UnionId(it) => Adt::Union(it.into()),
38 AdtId::EnumId(it) => Adt::Enum(it.into()),
39 }
40 }
41}
42
43impl From<EnumVariantId> for EnumVariant {
44 fn from(id: EnumVariantId) -> Self {
45 EnumVariant { parent: id.parent.into(), id: id.local_id }
46 }
47}
48
49impl From<ModuleDefId> for ModuleDef {
50 fn from(id: ModuleDefId) -> Self {
51 match id {
52 ModuleDefId::ModuleId(it) => ModuleDef::Module(it.into()),
53 ModuleDefId::FunctionId(it) => ModuleDef::Function(it.into()),
54 ModuleDefId::AdtId(it) => ModuleDef::Adt(it.into()),
55 ModuleDefId::EnumVariantId(it) => ModuleDef::EnumVariant(it.into()),
56 ModuleDefId::ConstId(it) => ModuleDef::Const(it.into()),
57 ModuleDefId::StaticId(it) => ModuleDef::Static(it.into()),
58 ModuleDefId::TraitId(it) => ModuleDef::Trait(it.into()),
59 ModuleDefId::TypeAliasId(it) => ModuleDef::TypeAlias(it.into()),
60 ModuleDefId::BuiltinType(it) => ModuleDef::BuiltinType(it),
61 }
62 }
63}
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index a9de01455..9899bdbbc 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -149,14 +149,20 @@ impl Module {
149 ModuleSource::SourceFile(_) => None, 149 ModuleSource::SourceFile(_) => None,
150 }; 150 };
151 151
152 db.relevant_crates(src.file_id.original_file(db)) 152 db.relevant_crates(src.file_id.original_file(db)).iter().find_map(|&crate_id| {
153 .iter() 153 let def_map = db.crate_def_map(crate_id);
154 .map(|&crate_id| Crate { crate_id }) 154
155 .find_map(|krate| { 155 let (module_id, _module_data) =
156 let def_map = db.crate_def_map(krate); 156 def_map.modules.iter().find(|(_module_id, module_data)| {
157 let module_id = def_map.find_module_by_source(src.file_id, decl_id)?; 157 if decl_id.is_some() {
158 Some(Module::new(krate, module_id)) 158 module_data.declaration == decl_id
159 }) 159 } else {
160 module_data.definition.map(|it| it.into()) == Some(src.file_id)
161 }
162 })?;
163
164 Some(Module::new(Crate { crate_id }, module_id))
165 })
160 } 166 }
161} 167}
162 168
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 52e1fbf29..9c261eda9 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -77,9 +77,10 @@ impl GenericParams {
77 let parent = match def { 77 let parent = match def {
78 GenericDef::Function(it) => it.container(db).map(GenericDef::from), 78 GenericDef::Function(it) => it.container(db).map(GenericDef::from),
79 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), 79 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from),
80 GenericDef::Const(it) => it.container(db).map(GenericDef::from),
80 GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()), 81 GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()),
81 GenericDef::Adt(_) | GenericDef::Trait(_) => None, 82 GenericDef::Adt(_) | GenericDef::Trait(_) => None,
82 GenericDef::ImplBlock(_) | GenericDef::Const(_) => None, 83 GenericDef::ImplBlock(_) => None,
83 }; 84 };
84 let mut generics = GenericParams { 85 let mut generics = GenericParams {
85 def, 86 def,
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 603b0c3dc..3ba99d92d 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -34,7 +34,6 @@ pub mod mock;
34pub mod source_binder; 34pub mod source_binder;
35 35
36mod ids; 36mod ids;
37mod nameres;
38mod adt; 37mod adt;
39mod traits; 38mod traits;
40mod type_alias; 39mod type_alias;
@@ -47,6 +46,7 @@ mod resolve;
47pub mod diagnostics; 46pub mod diagnostics;
48mod util; 47mod util;
49 48
49mod from_id;
50mod code_model; 50mod code_model;
51 51
52pub mod from_source; 52pub mod from_source;
@@ -62,17 +62,16 @@ pub use crate::{
62 adt::VariantDef, 62 adt::VariantDef,
63 code_model::{ 63 code_model::{
64 docs::{DocDef, Docs, Documentation}, 64 docs::{DocDef, Docs, Documentation},
65 src::{HasBodySource, HasSource, Source}, 65 src::{HasBodySource, HasSource},
66 Adt, AssocItem, BuiltinType, Const, ConstData, Container, Crate, CrateDependency, 66 Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
67 DefWithBody, Enum, EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, 67 EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef,
68 ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, 68 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
69 }, 69 },
70 expr::ExprScopes, 70 expr::ExprScopes,
71 from_source::FromSource, 71 from_source::FromSource,
72 generics::{GenericDef, GenericParam, GenericParams, HasGenericParams}, 72 generics::{GenericDef, GenericParam, GenericParams, HasGenericParams},
73 ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, 73 ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile},
74 impl_block::ImplBlock, 74 impl_block::ImplBlock,
75 nameres::{ImportId, Namespace, PerNs},
76 resolve::ScopeDef, 75 resolve::ScopeDef,
77 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 76 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
78 ty::{ 77 ty::{
@@ -81,7 +80,12 @@ pub use crate::{
81}; 80};
82 81
83pub use hir_def::{ 82pub use hir_def::{
83 builtin_type::BuiltinType,
84 nameres::{
85 per_ns::{Namespace, PerNs},
86 raw::ImportId,
87 },
84 path::{Path, PathKind}, 88 path::{Path, PathKind},
85 type_ref::Mutability, 89 type_ref::Mutability,
86}; 90};
87pub use hir_expand::{either::Either, name::Name}; 91pub use hir_expand::{either::Either, name::Name, Source};
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 35dfaf3ba..8d98f88ce 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -2,17 +2,17 @@
2 2
3use std::{panic, sync::Arc}; 3use std::{panic, sync::Arc};
4 4
5use hir_expand::diagnostics::DiagnosticSink;
5use parking_lot::Mutex; 6use parking_lot::Mutex;
6use ra_cfg::CfgOptions; 7use ra_cfg::CfgOptions;
7use ra_db::{ 8use ra_db::{
8 salsa, CrateGraph, CrateId, Edition, FileId, FileLoader, FileLoaderDelegate, FilePosition, 9 salsa, CrateGraph, CrateId, Edition, FileId, FileLoader, FileLoaderDelegate, FilePosition,
9 SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId, 10 RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
10}; 11};
11use relative_path::{RelativePath, RelativePathBuf};
12use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
13use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; 13use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
14 14
15use crate::{db, debug::HirDebugHelper, diagnostics::DiagnosticSink}; 15use crate::{db, debug::HirDebugHelper};
16 16
17pub const WORKSPACE: SourceRootId = SourceRootId(0); 17pub const WORKSPACE: SourceRootId = SourceRootId(0);
18 18
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
deleted file mode 100644
index 39f585b44..000000000
--- a/crates/ra_hir/src/nameres.rs
+++ /dev/null
@@ -1,559 +0,0 @@
1//! This module implements import-resolution/macro expansion algorithm.
2//!
3//! The result of this module is `CrateDefMap`: a data structure which contains:
4//!
5//! * a tree of modules for the crate
6//! * for each module, a set of items visible in the module (directly declared
7//! or imported)
8//!
9//! Note that `CrateDefMap` contains fully macro expanded code.
10//!
11//! Computing `CrateDefMap` can be partitioned into several logically
12//! independent "phases". The phases are mutually recursive though, there's no
13//! strict ordering.
14//!
15//! ## Collecting RawItems
16//!
17//! This happens in the `raw` module, which parses a single source file into a
18//! set of top-level items. Nested imports are desugared to flat imports in
19//! this phase. Macro calls are represented as a triple of (Path, Option<Name>,
20//! TokenTree).
21//!
22//! ## Collecting Modules
23//!
24//! This happens in the `collector` module. In this phase, we recursively walk
25//! tree of modules, collect raw items from submodules, populate module scopes
26//! with defined items (so, we assign item ids in this phase) and record the set
27//! of unresolved imports and macros.
28//!
29//! While we walk tree of modules, we also record macro_rules definitions and
30//! expand calls to macro_rules defined macros.
31//!
32//! ## Resolving Imports
33//!
34//! We maintain a list of currently unresolved imports. On every iteration, we
35//! try to resolve some imports from this list. If the import is resolved, we
36//! record it, by adding an item to current module scope and, if necessary, by
37//! recursively populating glob imports.
38//!
39//! ## Resolving Macros
40//!
41//! macro_rules from the same crate use a global mutable namespace. We expand
42//! them immediately, when we collect modules.
43//!
44//! Macros from other crates (including proc-macros) can be used with
45//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
46//! unexpanded macros. On every iteration, we try to resolve each macro call
47//! path and, upon success, we run macro expansion and "collect module" phase
48//! on the result
49
50mod per_ns;
51mod collector;
52mod mod_resolution;
53#[cfg(test)]
54mod tests;
55
56use std::sync::Arc;
57
58use hir_def::CrateModuleId;
59use once_cell::sync::Lazy;
60use ra_arena::Arena;
61use ra_db::{Edition, FileId};
62use ra_prof::profile;
63use ra_syntax::ast;
64use rustc_hash::{FxHashMap, FxHashSet};
65use test_utils::tested_by;
66
67use crate::{
68 db::{AstDatabase, DefDatabase},
69 diagnostics::DiagnosticSink,
70 ids::MacroDefId,
71 nameres::diagnostics::DefDiagnostic,
72 Adt, AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind,
73 Trait,
74};
75
76pub use self::per_ns::{Namespace, PerNs};
77
78pub use hir_def::nameres::raw::ImportId;
79
80/// Contains all top-level defs from a macro-expanded crate
81#[derive(Debug, PartialEq, Eq)]
82pub struct CrateDefMap {
83 krate: Crate,
84 edition: Edition,
85 /// The prelude module for this crate. This either comes from an import
86 /// marked with the `prelude_import` attribute, or (in the normal case) from
87 /// a dependency (`std` or `core`).
88 prelude: Option<Module>,
89 extern_prelude: FxHashMap<Name, ModuleDef>,
90 root: CrateModuleId,
91 modules: Arena<CrateModuleId, ModuleData>,
92
93 /// Some macros are not well-behavior, which leads to infinite loop
94 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
95 /// We mark it down and skip it in collector
96 ///
97 /// FIXME:
98 /// Right now it only handle a poison macro in a single crate,
99 /// such that if other crate try to call that macro,
100 /// the whole process will do again until it became poisoned in that crate.
101 /// We should handle this macro set globally
102 /// However, do we want to put it as a global variable?
103 poison_macros: FxHashSet<MacroDefId>,
104
105 diagnostics: Vec<DefDiagnostic>,
106}
107
108impl std::ops::Index<CrateModuleId> for CrateDefMap {
109 type Output = ModuleData;
110 fn index(&self, id: CrateModuleId) -> &ModuleData {
111 &self.modules[id]
112 }
113}
114
115#[derive(Default, Debug, PartialEq, Eq)]
116pub struct ModuleData {
117 pub(crate) parent: Option<CrateModuleId>,
118 pub(crate) children: FxHashMap<Name, CrateModuleId>,
119 pub(crate) scope: ModuleScope,
120 /// None for root
121 pub(crate) declaration: Option<AstId<ast::Module>>,
122 /// None for inline modules.
123 ///
124 /// Note that non-inline modules, by definition, live inside non-macro file.
125 pub(crate) definition: Option<FileId>,
126}
127
128#[derive(Debug, Default, PartialEq, Eq, Clone)]
129pub struct ModuleScope {
130 items: FxHashMap<Name, Resolution>,
131 /// Macros visable in current module in legacy textual scope
132 ///
133 /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
134 /// If it yields no result, then it turns to module scoped `macros`.
135 /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
136 /// and only normal scoped `macros` will be searched in.
137 ///
138 /// Note that this automatically inherit macros defined textually before the definition of module itself.
139 ///
140 /// Module scoped macros will be inserted into `items` instead of here.
141 // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
142 // be all resolved to the last one defined if shadowing happens.
143 legacy_macros: FxHashMap<Name, MacroDef>,
144}
145
146static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
147 BuiltinType::ALL
148 .iter()
149 .map(|(name, ty)| {
150 (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
151 })
152 .collect()
153});
154
155/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
156/// Other methods will only resolve values, types and module scoped macros only.
157impl ModuleScope {
158 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
159 //FIXME: shadowing
160 self.items.iter().chain(BUILTIN_SCOPE.iter())
161 }
162
163 /// Iterate over all module scoped macros
164 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a {
165 self.items
166 .iter()
167 .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_)))
168 }
169
170 /// Iterate over all legacy textual scoped macros visable at the end of the module
171 pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a {
172 self.legacy_macros.iter().map(|(name, def)| (name, *def))
173 }
174
175 /// Get a name from current module scope, legacy macros are not included
176 pub fn get(&self, name: &Name) -> Option<&Resolution> {
177 self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name))
178 }
179
180 pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a {
181 self.items.values().filter_map(|r| match r.def.take_types() {
182 Some(ModuleDef::Trait(t)) => Some(t),
183 _ => None,
184 })
185 }
186
187 fn get_legacy_macro(&self, name: &Name) -> Option<MacroDef> {
188 self.legacy_macros.get(name).copied()
189 }
190}
191
192#[derive(Debug, Clone, PartialEq, Eq, Default)]
193pub struct Resolution {
194 /// None for unresolved
195 pub def: PerNs,
196 /// ident by which this is imported into local scope.
197 pub import: Option<ImportId>,
198}
199
200impl Resolution {
201 pub(crate) fn from_macro(macro_: MacroDef) -> Self {
202 Resolution { def: PerNs::macros(macro_), import: None }
203 }
204}
205
206#[derive(Debug, Clone)]
207struct ResolvePathResult {
208 resolved_def: PerNs,
209 segment_index: Option<usize>,
210 reached_fixedpoint: ReachedFixedPoint,
211}
212
213impl ResolvePathResult {
214 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
215 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
216 }
217
218 fn with(
219 resolved_def: PerNs,
220 reached_fixedpoint: ReachedFixedPoint,
221 segment_index: Option<usize>,
222 ) -> ResolvePathResult {
223 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index }
224 }
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
228enum ResolveMode {
229 Import,
230 Other,
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq)]
234enum ReachedFixedPoint {
235 Yes,
236 No,
237}
238
239impl CrateDefMap {
240 pub(crate) fn crate_def_map_query(
241 // Note that this doesn't have `+ AstDatabase`!
242 // This gurantess that `CrateDefMap` is stable across reparses.
243 db: &impl DefDatabase,
244 krate: Crate,
245 ) -> Arc<CrateDefMap> {
246 let _p = profile("crate_def_map_query");
247 let def_map = {
248 let edition = krate.edition(db);
249 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default();
250 let root = modules.alloc(ModuleData::default());
251 CrateDefMap {
252 krate,
253 edition,
254 extern_prelude: FxHashMap::default(),
255 prelude: None,
256 root,
257 modules,
258 poison_macros: FxHashSet::default(),
259 diagnostics: Vec::new(),
260 }
261 };
262 let def_map = collector::collect_defs(db, def_map);
263 Arc::new(def_map)
264 }
265
266 pub(crate) fn krate(&self) -> Crate {
267 self.krate
268 }
269
270 pub(crate) fn root(&self) -> CrateModuleId {
271 self.root
272 }
273
274 pub(crate) fn prelude(&self) -> Option<Module> {
275 self.prelude
276 }
277
278 pub(crate) fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDef> {
279 &self.extern_prelude
280 }
281
282 pub(crate) fn add_diagnostics(
283 &self,
284 db: &(impl DefDatabase + AstDatabase),
285 module: CrateModuleId,
286 sink: &mut DiagnosticSink,
287 ) {
288 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
289 }
290
291 pub(crate) fn find_module_by_source(
292 &self,
293 file_id: HirFileId,
294 decl_id: Option<AstId<ast::Module>>,
295 ) -> Option<CrateModuleId> {
296 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
297 if decl_id.is_some() {
298 module_data.declaration == decl_id
299 } else {
300 module_data.definition.map(|it| it.into()) == Some(file_id)
301 }
302 })?;
303 Some(module_id)
304 }
305
306 pub(crate) fn resolve_path(
307 &self,
308 db: &impl DefDatabase,
309 original_module: CrateModuleId,
310 path: &Path,
311 ) -> (PerNs, Option<usize>) {
312 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
313 (res.resolved_def, res.segment_index)
314 }
315
316 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
317 // the result.
318 fn resolve_path_fp_with_macro(
319 &self,
320 db: &impl DefDatabase,
321 mode: ResolveMode,
322 original_module: CrateModuleId,
323 path: &Path,
324 ) -> ResolvePathResult {
325 let mut segments = path.segments.iter().enumerate();
326 let mut curr_per_ns: PerNs = match path.kind {
327 PathKind::DollarCrate(crate_id) => {
328 let krate = Crate { crate_id };
329 if krate == self.krate {
330 tested_by!(macro_dollar_crate_self);
331 PerNs::types(Module::new(self.krate, self.root).into())
332 } else {
333 match krate.root_module(db) {
334 Some(module) => {
335 tested_by!(macro_dollar_crate_other);
336 PerNs::types(module.into())
337 }
338 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
339 }
340 }
341 }
342 PathKind::Crate => PerNs::types(Module::new(self.krate, self.root).into()),
343 PathKind::Self_ => PerNs::types(Module::new(self.krate, original_module).into()),
344 // plain import or absolute path in 2015: crate-relative with
345 // fallback to extern prelude (with the simplification in
346 // rust-lang/rust#57745)
347 // FIXME there must be a nicer way to write this condition
348 PathKind::Plain | PathKind::Abs
349 if self.edition == Edition::Edition2015
350 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
351 {
352 let segment = match segments.next() {
353 Some((_, segment)) => segment,
354 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
355 };
356 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
357 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
358 }
359 PathKind::Plain => {
360 let segment = match segments.next() {
361 Some((_, segment)) => segment,
362 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
363 };
364 log::debug!("resolving {:?} in module", segment);
365 self.resolve_name_in_module(db, original_module, &segment.name)
366 }
367 PathKind::Super => {
368 if let Some(p) = self.modules[original_module].parent {
369 PerNs::types(Module::new(self.krate, p).into())
370 } else {
371 log::debug!("super path in root module");
372 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
373 }
374 }
375 PathKind::Abs => {
376 // 2018-style absolute path -- only extern prelude
377 let segment = match segments.next() {
378 Some((_, segment)) => segment,
379 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
380 };
381 if let Some(def) = self.extern_prelude.get(&segment.name) {
382 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
383 PerNs::types(*def)
384 } else {
385 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
386 }
387 }
388 PathKind::Type(_) => {
389 // This is handled in `infer::infer_path_expr`
390 // The result returned here does not matter
391 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
392 }
393 };
394
395 for (i, segment) in segments {
396 let curr = match curr_per_ns.take_types() {
397 Some(r) => r,
398 None => {
399 // we still have path segments left, but the path so far
400 // didn't resolve in the types namespace => no resolution
401 // (don't break here because `curr_per_ns` might contain
402 // something in the value namespace, and it would be wrong
403 // to return that)
404 return ResolvePathResult::empty(ReachedFixedPoint::No);
405 }
406 };
407 // resolve segment in curr
408
409 curr_per_ns = match curr {
410 ModuleDef::Module(module) => {
411 if module.krate() != self.krate {
412 let path =
413 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
414 log::debug!("resolving {:?} in other crate", path);
415 let defp_map = db.crate_def_map(module.krate());
416 let (def, s) = defp_map.resolve_path(db, module.id.module_id, &path);
417 return ResolvePathResult::with(
418 def,
419 ReachedFixedPoint::Yes,
420 s.map(|s| s + i),
421 );
422 }
423
424 // Since it is a qualified path here, it should not contains legacy macros
425 match self[module.id.module_id].scope.get(&segment.name) {
426 Some(res) => res.def,
427 _ => {
428 log::debug!("path segment {:?} not found", segment.name);
429 return ResolvePathResult::empty(ReachedFixedPoint::No);
430 }
431 }
432 }
433 ModuleDef::Adt(Adt::Enum(e)) => {
434 // enum variant
435 tested_by!(can_import_enum_variant);
436 match e.variant(db, &segment.name) {
437 Some(variant) => PerNs::both(variant.into(), variant.into()),
438 None => {
439 return ResolvePathResult::with(
440 PerNs::types(e.into()),
441 ReachedFixedPoint::Yes,
442 Some(i),
443 );
444 }
445 }
446 }
447 s => {
448 // could be an inherent method call in UFCS form
449 // (`Struct::method`), or some other kind of associated item
450 log::debug!(
451 "path segment {:?} resolved to non-module {:?}, but is not last",
452 segment.name,
453 curr,
454 );
455
456 return ResolvePathResult::with(
457 PerNs::types(s),
458 ReachedFixedPoint::Yes,
459 Some(i),
460 );
461 }
462 };
463 }
464 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
465 }
466
467 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs {
468 let from_crate_root =
469 self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
470 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
471
472 from_crate_root.or(from_extern_prelude)
473 }
474
475 pub(crate) fn resolve_name_in_module(
476 &self,
477 db: &impl DefDatabase,
478 module: CrateModuleId,
479 name: &Name,
480 ) -> PerNs {
481 // Resolve in:
482 // - legacy scope of macro
483 // - current module / scope
484 // - extern prelude
485 // - std prelude
486 let from_legacy_macro =
487 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
488 let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
489 let from_extern_prelude =
490 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
491 let from_prelude = self.resolve_in_prelude(db, name);
492
493 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
494 }
495
496 fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
497 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
498 }
499
500 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
501 if let Some(prelude) = self.prelude {
502 let keep;
503 let def_map = if prelude.krate() == self.krate {
504 self
505 } else {
506 // Extend lifetime
507 keep = db.crate_def_map(prelude.krate());
508 &keep
509 };
510 def_map[prelude.id.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
511 } else {
512 PerNs::none()
513 }
514 }
515}
516
517mod diagnostics {
518 use ra_syntax::{ast, AstPtr};
519 use relative_path::RelativePathBuf;
520
521 use crate::{
522 db::{AstDatabase, DefDatabase},
523 diagnostics::{DiagnosticSink, UnresolvedModule},
524 nameres::CrateModuleId,
525 AstId,
526 };
527
528 #[derive(Debug, PartialEq, Eq)]
529 pub(super) enum DefDiagnostic {
530 UnresolvedModule {
531 module: CrateModuleId,
532 declaration: AstId<ast::Module>,
533 candidate: RelativePathBuf,
534 },
535 }
536
537 impl DefDiagnostic {
538 pub(super) fn add_to(
539 &self,
540 db: &(impl DefDatabase + AstDatabase),
541 target_module: CrateModuleId,
542 sink: &mut DiagnosticSink,
543 ) {
544 match self {
545 DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
546 if *module != target_module {
547 return;
548 }
549 let decl = declaration.to_node(db);
550 sink.push(UnresolvedModule {
551 file: declaration.file_id(),
552 decl: AstPtr::new(&decl),
553 candidate: candidate.clone(),
554 })
555 }
556 }
557 }
558 }
559}
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
deleted file mode 100644
index e2e13805a..000000000
--- a/crates/ra_hir/src/nameres/collector.rs
+++ /dev/null
@@ -1,834 +0,0 @@
1//! FIXME: write short doc here
2
3use hir_def::{attr::Attr, nameres::raw};
4use hir_expand::name;
5use ra_cfg::CfgOptions;
6use ra_db::FileId;
7use ra_syntax::{ast, SmolStr};
8use rustc_hash::FxHashMap;
9use test_utils::tested_by;
10
11use crate::{
12 db::DefDatabase,
13 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
14 nameres::{
15 diagnostics::DefDiagnostic, mod_resolution::ModDir, Crate, CrateDefMap, CrateModuleId,
16 ModuleData, ModuleDef, PerNs, ReachedFixedPoint, Resolution, ResolveMode,
17 },
18 Adt, AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static,
19 Struct, Trait, TypeAlias, Union,
20};
21
22pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
23 // populate external prelude
24 for dep in def_map.krate.dependencies(db) {
25 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
26 if let Some(module) = dep.krate.root_module(db) {
27 def_map.extern_prelude.insert(dep.name.clone(), module.into());
28 }
29 // look for the prelude
30 if def_map.prelude.is_none() {
31 let map = db.crate_def_map(dep.krate);
32 if map.prelude.is_some() {
33 def_map.prelude = map.prelude;
34 }
35 }
36 }
37
38 let crate_graph = db.crate_graph();
39 let cfg_options = crate_graph.cfg_options(def_map.krate().crate_id());
40
41 let mut collector = DefCollector {
42 db,
43 def_map,
44 glob_imports: FxHashMap::default(),
45 unresolved_imports: Vec::new(),
46 unexpanded_macros: Vec::new(),
47 mod_dirs: FxHashMap::default(),
48 macro_stack_monitor: MacroStackMonitor::default(),
49 cfg_options,
50 };
51 collector.collect();
52 collector.finish()
53}
54
55#[derive(Default)]
56struct MacroStackMonitor {
57 counts: FxHashMap<MacroDefId, u32>,
58
59 /// Mainly use for test
60 validator: Option<Box<dyn Fn(u32) -> bool>>,
61}
62
63impl MacroStackMonitor {
64 fn increase(&mut self, macro_def_id: MacroDefId) {
65 *self.counts.entry(macro_def_id).or_default() += 1;
66 }
67
68 fn decrease(&mut self, macro_def_id: MacroDefId) {
69 *self.counts.entry(macro_def_id).or_default() -= 1;
70 }
71
72 fn is_poison(&self, macro_def_id: MacroDefId) -> bool {
73 let cur = *self.counts.get(&macro_def_id).unwrap_or(&0);
74
75 if let Some(validator) = &self.validator {
76 validator(cur)
77 } else {
78 cur > 100
79 }
80 }
81}
82
83/// Walks the tree of module recursively
84struct DefCollector<'a, DB> {
85 db: &'a DB,
86 def_map: CrateDefMap,
87 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
88 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
89 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>,
90 mod_dirs: FxHashMap<CrateModuleId, ModDir>,
91
92 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
93 /// To prevent stack overflow, we add a deep counter here for prevent that.
94 macro_stack_monitor: MacroStackMonitor,
95
96 cfg_options: &'a CfgOptions,
97}
98
99impl<DB> DefCollector<'_, DB>
100where
101 DB: DefDatabase,
102{
103 fn collect(&mut self) {
104 let crate_graph = self.db.crate_graph();
105 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
106 let raw_items = self.db.raw_items(file_id.into());
107 let module_id = self.def_map.root;
108 self.def_map.modules[module_id].definition = Some(file_id);
109 ModCollector {
110 def_collector: &mut *self,
111 module_id,
112 file_id: file_id.into(),
113 raw_items: &raw_items,
114 mod_dir: ModDir::root(),
115 }
116 .collect(raw_items.items());
117
118 // main name resolution fixed-point loop.
119 let mut i = 0;
120 loop {
121 self.db.check_canceled();
122 match (self.resolve_imports(), self.resolve_macros()) {
123 (ReachedFixedPoint::Yes, ReachedFixedPoint::Yes) => break,
124 _ => i += 1,
125 }
126 if i == 1000 {
127 log::error!("name resolution is stuck");
128 break;
129 }
130 }
131
132 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
133 // show unresolved imports in completion, etc
134 for (module_id, import, import_data) in unresolved_imports {
135 self.record_resolved_import(module_id, PerNs::none(), import, &import_data)
136 }
137 }
138
139 /// Define a macro with `macro_rules`.
140 ///
141 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
142 /// then it is also defined in the root module scope.
143 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
144 ///
145 /// It is surprising that the macro will never be in the current module scope.
146 /// These code fails with "unresolved import/macro",
147 /// ```rust,compile_fail
148 /// mod m { macro_rules! foo { () => {} } }
149 /// use m::foo as bar;
150 /// ```
151 ///
152 /// ```rust,compile_fail
153 /// macro_rules! foo { () => {} }
154 /// self::foo!();
155 /// crate::foo!();
156 /// ```
157 ///
158 /// Well, this code compiles, bacause the plain path `foo` in `use` is searched
159 /// in the legacy textual scope only.
160 /// ```rust
161 /// macro_rules! foo { () => {} }
162 /// use foo as bar;
163 /// ```
164 fn define_macro(
165 &mut self,
166 module_id: CrateModuleId,
167 name: Name,
168 macro_: MacroDef,
169 export: bool,
170 ) {
171 // Textual scoping
172 self.define_legacy_macro(module_id, name.clone(), macro_);
173
174 // Module scoping
175 // In Rust, `#[macro_export]` macros are unconditionally visible at the
176 // crate root, even if the parent modules is **not** visible.
177 if export {
178 self.update(self.def_map.root, None, &[(name, Resolution::from_macro(macro_))]);
179 }
180 }
181
182 /// Define a legacy textual scoped macro in module
183 ///
184 /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module.
185 /// It will clone all macros from parent legacy scope, whose definition is prior to
186 /// the definition of current module.
187 /// And also, `macro_use` on a module will import all legacy macros visable inside to
188 /// current legacy scope, with possible shadowing.
189 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDef) {
190 // Always shadowing
191 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
192 }
193
194 /// Import macros from `#[macro_use] extern crate`.
195 fn import_macros_from_extern_crate(
196 &mut self,
197 current_module_id: CrateModuleId,
198 import: &raw::ImportData,
199 ) {
200 log::debug!(
201 "importing macros from extern crate: {:?} ({:?})",
202 import,
203 self.def_map.edition,
204 );
205
206 let res = self.def_map.resolve_name_in_extern_prelude(
207 &import
208 .path
209 .as_ident()
210 .expect("extern crate should have been desugared to one-element path"),
211 );
212
213 if let Some(ModuleDef::Module(m)) = res.take_types() {
214 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
215 self.import_all_macros_exported(current_module_id, m.krate());
216 }
217 }
218
219 /// Import all exported macros from another crate
220 ///
221 /// Exported macros are just all macros in the root module scope.
222 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
223 /// created by `use` in the root module, ignoring the visibility of `use`.
224 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: Crate) {
225 let def_map = self.db.crate_def_map(krate);
226 for (name, def) in def_map[def_map.root].scope.macros() {
227 // `macro_use` only bring things into legacy scope.
228 self.define_legacy_macro(current_module_id, name.clone(), def);
229 }
230 }
231
232 fn resolve_imports(&mut self) -> ReachedFixedPoint {
233 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
234 let mut resolved = Vec::new();
235 imports.retain(|(module_id, import, import_data)| {
236 let (def, fp) = self.resolve_import(*module_id, import_data);
237 if fp == ReachedFixedPoint::Yes {
238 resolved.push((*module_id, def, *import, import_data.clone()))
239 }
240 fp == ReachedFixedPoint::No
241 });
242 self.unresolved_imports = imports;
243 // Resolves imports, filling-in module scopes
244 let result =
245 if resolved.is_empty() { ReachedFixedPoint::Yes } else { ReachedFixedPoint::No };
246 for (module_id, def, import, import_data) in resolved {
247 self.record_resolved_import(module_id, def, import, &import_data)
248 }
249 result
250 }
251
252 fn resolve_import(
253 &self,
254 module_id: CrateModuleId,
255 import: &raw::ImportData,
256 ) -> (PerNs, ReachedFixedPoint) {
257 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
258 if import.is_extern_crate {
259 let res = self.def_map.resolve_name_in_extern_prelude(
260 &import
261 .path
262 .as_ident()
263 .expect("extern crate should have been desugared to one-element path"),
264 );
265 (res, ReachedFixedPoint::Yes)
266 } else {
267 let res = self.def_map.resolve_path_fp_with_macro(
268 self.db,
269 ResolveMode::Import,
270 module_id,
271 &import.path,
272 );
273
274 (res.resolved_def, res.reached_fixedpoint)
275 }
276 }
277
278 fn record_resolved_import(
279 &mut self,
280 module_id: CrateModuleId,
281 def: PerNs,
282 import_id: raw::ImportId,
283 import: &raw::ImportData,
284 ) {
285 if import.is_glob {
286 log::debug!("glob import: {:?}", import);
287 match def.take_types() {
288 Some(ModuleDef::Module(m)) => {
289 if import.is_prelude {
290 tested_by!(std_prelude);
291 self.def_map.prelude = Some(m);
292 } else if m.krate() != self.def_map.krate {
293 tested_by!(glob_across_crates);
294 // glob import from other crate => we can just import everything once
295 let item_map = self.db.crate_def_map(m.krate());
296 let scope = &item_map[m.id.module_id].scope;
297
298 // Module scoped macros is included
299 let items = scope
300 .items
301 .iter()
302 .map(|(name, res)| (name.clone(), res.clone()))
303 .collect::<Vec<_>>();
304
305 self.update(module_id, Some(import_id), &items);
306 } else {
307 // glob import from same crate => we do an initial
308 // import, and then need to propagate any further
309 // additions
310 let scope = &self.def_map[m.id.module_id].scope;
311
312 // Module scoped macros is included
313 let items = scope
314 .items
315 .iter()
316 .map(|(name, res)| (name.clone(), res.clone()))
317 .collect::<Vec<_>>();
318
319 self.update(module_id, Some(import_id), &items);
320 // record the glob import in case we add further items
321 self.glob_imports
322 .entry(m.id.module_id)
323 .or_default()
324 .push((module_id, import_id));
325 }
326 }
327 Some(ModuleDef::Adt(Adt::Enum(e))) => {
328 tested_by!(glob_enum);
329 // glob import from enum => just import all the variants
330 let variants = e.variants(self.db);
331 let resolutions = variants
332 .into_iter()
333 .filter_map(|variant| {
334 let res = Resolution {
335 def: PerNs::both(variant.into(), variant.into()),
336 import: Some(import_id),
337 };
338 let name = variant.name(self.db)?;
339 Some((name, res))
340 })
341 .collect::<Vec<_>>();
342 self.update(module_id, Some(import_id), &resolutions);
343 }
344 Some(d) => {
345 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
346 }
347 None => {
348 log::debug!("glob import {:?} didn't resolve as type", import);
349 }
350 }
351 } else {
352 match import.path.segments.last() {
353 Some(last_segment) => {
354 let name = import.alias.clone().unwrap_or_else(|| last_segment.name.clone());
355 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
356
357 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
358 if import.is_extern_crate && module_id == self.def_map.root {
359 if let Some(def) = def.take_types() {
360 self.def_map.extern_prelude.insert(name.clone(), def);
361 }
362 }
363
364 let resolution = Resolution { def, import: Some(import_id) };
365 self.update(module_id, Some(import_id), &[(name, resolution)]);
366 }
367 None => tested_by!(bogus_paths),
368 }
369 }
370 }
371
372 fn update(
373 &mut self,
374 module_id: CrateModuleId,
375 import: Option<raw::ImportId>,
376 resolutions: &[(Name, Resolution)],
377 ) {
378 self.update_recursive(module_id, import, resolutions, 0)
379 }
380
381 fn update_recursive(
382 &mut self,
383 module_id: CrateModuleId,
384 import: Option<raw::ImportId>,
385 resolutions: &[(Name, Resolution)],
386 depth: usize,
387 ) {
388 if depth > 100 {
389 // prevent stack overflows (but this shouldn't be possible)
390 panic!("infinite recursion in glob imports!");
391 }
392 let module_items = &mut self.def_map.modules[module_id].scope;
393 let mut changed = false;
394 for (name, res) in resolutions {
395 let existing = module_items.items.entry(name.clone()).or_default();
396
397 if existing.def.types.is_none() && res.def.types.is_some() {
398 existing.def.types = res.def.types;
399 existing.import = import.or(res.import);
400 changed = true;
401 }
402 if existing.def.values.is_none() && res.def.values.is_some() {
403 existing.def.values = res.def.values;
404 existing.import = import.or(res.import);
405 changed = true;
406 }
407 if existing.def.macros.is_none() && res.def.macros.is_some() {
408 existing.def.macros = res.def.macros;
409 existing.import = import.or(res.import);
410 changed = true;
411 }
412
413 if existing.def.is_none()
414 && res.def.is_none()
415 && existing.import.is_none()
416 && res.import.is_some()
417 {
418 existing.import = res.import;
419 }
420 }
421
422 if !changed {
423 return;
424 }
425 let glob_imports = self
426 .glob_imports
427 .get(&module_id)
428 .into_iter()
429 .flat_map(|v| v.iter())
430 .cloned()
431 .collect::<Vec<_>>();
432 for (glob_importing_module, glob_import) in glob_imports {
433 // We pass the glob import so that the tracked import in those modules is that glob import
434 self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
435 }
436 }
437
438 fn resolve_macros(&mut self) -> ReachedFixedPoint {
439 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
440 let mut resolved = Vec::new();
441 let mut res = ReachedFixedPoint::Yes;
442 macros.retain(|(module_id, ast_id, path)| {
443 let resolved_res = self.def_map.resolve_path_fp_with_macro(
444 self.db,
445 ResolveMode::Other,
446 *module_id,
447 path,
448 );
449
450 if let Some(def) = resolved_res.resolved_def.get_macros() {
451 let call_id = self.db.intern_macro(MacroCallLoc { def: def.id, ast_id: *ast_id });
452 resolved.push((*module_id, call_id, def.id));
453 res = ReachedFixedPoint::No;
454 return false;
455 }
456
457 true
458 });
459
460 self.unexpanded_macros = macros;
461
462 for (module_id, macro_call_id, macro_def_id) in resolved {
463 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id);
464 }
465
466 res
467 }
468
469 fn collect_macro_expansion(
470 &mut self,
471 module_id: CrateModuleId,
472 macro_call_id: MacroCallId,
473 macro_def_id: MacroDefId,
474 ) {
475 if self.def_map.poison_macros.contains(&macro_def_id) {
476 return;
477 }
478
479 self.macro_stack_monitor.increase(macro_def_id);
480
481 if !self.macro_stack_monitor.is_poison(macro_def_id) {
482 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
483 let raw_items = self.db.raw_items(file_id);
484 let mod_dir = self.mod_dirs[&module_id].clone();
485 ModCollector {
486 def_collector: &mut *self,
487 file_id,
488 module_id,
489 raw_items: &raw_items,
490 mod_dir,
491 }
492 .collect(raw_items.items());
493 } else {
494 log::error!("Too deep macro expansion: {:?}", macro_call_id);
495 self.def_map.poison_macros.insert(macro_def_id);
496 }
497
498 self.macro_stack_monitor.decrease(macro_def_id);
499 }
500
501 fn finish(self) -> CrateDefMap {
502 self.def_map
503 }
504}
505
506/// Walks a single module, populating defs, imports and macros
507struct ModCollector<'a, D> {
508 def_collector: D,
509 module_id: CrateModuleId,
510 file_id: HirFileId,
511 raw_items: &'a raw::RawItems,
512 mod_dir: ModDir,
513}
514
515impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
516where
517 DB: DefDatabase,
518{
519 fn collect(&mut self, items: &[raw::RawItem]) {
520 // Note: don't assert that inserted value is fresh: it's simply not true
521 // for macros.
522 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
523
524 // Prelude module is always considered to be `#[macro_use]`.
525 if let Some(prelude_module) = self.def_collector.def_map.prelude {
526 if prelude_module.krate() != self.def_collector.def_map.krate {
527 tested_by!(prelude_is_macro_use);
528 self.def_collector
529 .import_all_macros_exported(self.module_id, prelude_module.krate());
530 }
531 }
532
533 // This should be processed eagerly instead of deferred to resolving.
534 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
535 // any other items.
536 for item in items {
537 if self.is_cfg_enabled(item.attrs()) {
538 if let raw::RawItemKind::Import(import_id) = item.kind {
539 let import = self.raw_items[import_id].clone();
540 if import.is_extern_crate && import.is_macro_use {
541 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
542 }
543 }
544 }
545 }
546
547 for item in items {
548 if self.is_cfg_enabled(item.attrs()) {
549 match item.kind {
550 raw::RawItemKind::Module(m) => {
551 self.collect_module(&self.raw_items[m], item.attrs())
552 }
553 raw::RawItemKind::Import(import_id) => self
554 .def_collector
555 .unresolved_imports
556 .push((self.module_id, import_id, self.raw_items[import_id].clone())),
557 raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]),
558 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
559 }
560 }
561 }
562 }
563
564 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &[Attr]) {
565 let path_attr = self.path_attr(attrs);
566 let is_macro_use = self.is_macro_use(attrs);
567 match module {
568 // inline module, just recurse
569 raw::ModuleData::Definition { name, items, ast_id } => {
570 let module_id =
571 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
572
573 ModCollector {
574 def_collector: &mut *self.def_collector,
575 module_id,
576 file_id: self.file_id,
577 raw_items: self.raw_items,
578 mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
579 }
580 .collect(&*items);
581 if is_macro_use {
582 self.import_all_legacy_macros(module_id);
583 }
584 }
585 // out of line module, resolve, parse and recurse
586 raw::ModuleData::Declaration { name, ast_id } => {
587 let ast_id = AstId::new(self.file_id, *ast_id);
588 match self.mod_dir.resolve_declaration(
589 self.def_collector.db,
590 self.file_id,
591 name,
592 path_attr,
593 ) {
594 Ok((file_id, mod_dir)) => {
595 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
596 let raw_items = self.def_collector.db.raw_items(file_id.into());
597 ModCollector {
598 def_collector: &mut *self.def_collector,
599 module_id,
600 file_id: file_id.into(),
601 raw_items: &raw_items,
602 mod_dir,
603 }
604 .collect(raw_items.items());
605 if is_macro_use {
606 self.import_all_legacy_macros(module_id);
607 }
608 }
609 Err(candidate) => self.def_collector.def_map.diagnostics.push(
610 DefDiagnostic::UnresolvedModule {
611 module: self.module_id,
612 declaration: ast_id,
613 candidate,
614 },
615 ),
616 };
617 }
618 }
619 }
620
621 fn push_child_module(
622 &mut self,
623 name: Name,
624 declaration: AstId<ast::Module>,
625 definition: Option<FileId>,
626 ) -> CrateModuleId {
627 let modules = &mut self.def_collector.def_map.modules;
628 let res = modules.alloc(ModuleData::default());
629 modules[res].parent = Some(self.module_id);
630 modules[res].declaration = Some(declaration);
631 modules[res].definition = definition;
632 modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
633 modules[self.module_id].children.insert(name.clone(), res);
634 let resolution = Resolution {
635 def: PerNs::types(Module::new(self.def_collector.def_map.krate, res).into()),
636 import: None,
637 };
638 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
639 res
640 }
641
642 fn define_def(&mut self, def: &raw::DefData) {
643 let module = Module::new(self.def_collector.def_map.krate, self.module_id);
644 let ctx = LocationCtx::new(self.def_collector.db, module.id, self.file_id);
645
646 macro_rules! def {
647 ($kind:ident, $ast_id:ident) => {
648 $kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into()
649 };
650 }
651 let name = def.name.clone();
652 let def: PerNs = match def.kind {
653 raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)),
654 raw::DefKind::Struct(ast_id) => {
655 let s = def!(Struct, ast_id);
656 PerNs::both(s, s)
657 }
658 raw::DefKind::Union(ast_id) => {
659 let s = def!(Union, ast_id);
660 PerNs::both(s, s)
661 }
662 raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)),
663 raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)),
664 raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)),
665 raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)),
666 raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
667 };
668 let resolution = Resolution { def, import: None };
669 self.def_collector.update(self.module_id, None, &[(name, resolution)])
670 }
671
672 fn collect_macro(&mut self, mac: &raw::MacroData) {
673 let ast_id = AstId::new(self.file_id, mac.ast_id);
674
675 // Case 1: macro rules, define a macro in crate-global mutable scope
676 if is_macro_rules(&mac.path) {
677 if let Some(name) = &mac.name {
678 let macro_id =
679 MacroDefId { ast_id, krate: self.def_collector.def_map.krate.crate_id };
680 let macro_ = MacroDef { id: macro_id };
681 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export);
682 }
683 return;
684 }
685
686 // Case 2: try to resolve in legacy scope and expand macro_rules, triggering
687 // recursive item collection.
688 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
689 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
690 }) {
691 let def = macro_def.id;
692 let macro_call_id = self.def_collector.db.intern_macro(MacroCallLoc { def, ast_id });
693
694 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, def);
695 return;
696 }
697
698 // Case 3: resolve in module scope, expand during name resolution.
699 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
700 let mut path = mac.path.clone();
701 if path.is_ident() {
702 path.kind = PathKind::Self_;
703 }
704 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path));
705 }
706
707 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) {
708 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
709 for (name, macro_) in macros {
710 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
711 }
712 }
713
714 fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool {
715 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false))
716 }
717
718 fn path_attr<'a>(&self, attrs: &'a [Attr]) -> Option<&'a SmolStr> {
719 attrs.iter().find_map(|attr| attr.as_path())
720 }
721
722 fn is_macro_use<'a>(&self, attrs: &'a [Attr]) -> bool {
723 attrs.iter().any(|attr| attr.is_simple_atom("macro_use"))
724 }
725}
726
727fn is_macro_rules(path: &Path) -> bool {
728 path.as_ident() == Some(&name::MACRO_RULES)
729}
730
731#[cfg(test)]
732mod tests {
733 use ra_db::SourceDatabase;
734
735 use super::*;
736 use crate::{db::DefDatabase, mock::MockDatabase, Crate};
737 use ra_arena::Arena;
738 use rustc_hash::FxHashSet;
739
740 fn do_collect_defs(
741 db: &impl DefDatabase,
742 def_map: CrateDefMap,
743 monitor: MacroStackMonitor,
744 ) -> CrateDefMap {
745 let mut collector = DefCollector {
746 db,
747 def_map,
748 glob_imports: FxHashMap::default(),
749 unresolved_imports: Vec::new(),
750 unexpanded_macros: Vec::new(),
751 mod_dirs: FxHashMap::default(),
752 macro_stack_monitor: monitor,
753 cfg_options: &CfgOptions::default(),
754 };
755 collector.collect();
756 collector.finish()
757 }
758
759 fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap {
760 let (db, _source_root, _) = MockDatabase::with_single_file(&code);
761 let crate_id = db.crate_graph().iter().next().unwrap();
762 let krate = Crate { crate_id };
763
764 let def_map = {
765 let edition = krate.edition(&db);
766 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default();
767 let root = modules.alloc(ModuleData::default());
768 CrateDefMap {
769 krate,
770 edition,
771 extern_prelude: FxHashMap::default(),
772 prelude: None,
773 root,
774 modules,
775 poison_macros: FxHashSet::default(),
776 diagnostics: Vec::new(),
777 }
778 };
779
780 let mut monitor = MacroStackMonitor::default();
781 monitor.validator = Some(Box::new(move |count| {
782 assert!(count < limit);
783 count >= poison_limit
784 }));
785
786 do_collect_defs(&db, def_map, monitor)
787 }
788
789 #[test]
790 fn test_macro_expand_limit_width() {
791 do_limited_resolve(
792 r#"
793 macro_rules! foo {
794 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }
795 }
796foo!(KABOOM);
797 "#,
798 16,
799 1000,
800 );
801 }
802
803 #[test]
804 fn test_macro_expand_poisoned() {
805 let def = do_limited_resolve(
806 r#"
807 macro_rules! foo {
808 ($ty:ty) => { foo!($ty); }
809 }
810foo!(KABOOM);
811 "#,
812 100,
813 16,
814 );
815
816 assert_eq!(def.poison_macros.len(), 1);
817 }
818
819 #[test]
820 fn test_macro_expand_normal() {
821 let def = do_limited_resolve(
822 r#"
823 macro_rules! foo {
824 ($ident:ident) => { struct $ident {} }
825 }
826foo!(Bar);
827 "#,
828 16,
829 16,
830 );
831
832 assert_eq!(def.poison_macros.len(), 0);
833 }
834}
diff --git a/crates/ra_hir/src/nameres/mod_resolution.rs b/crates/ra_hir/src/nameres/mod_resolution.rs
deleted file mode 100644
index 334cdd692..000000000
--- a/crates/ra_hir/src/nameres/mod_resolution.rs
+++ /dev/null
@@ -1,80 +0,0 @@
1//! This module resolves `mod foo;` declaration to file.
2use ra_db::FileId;
3use ra_syntax::SmolStr;
4use relative_path::RelativePathBuf;
5
6use crate::{db::DefDatabase, HirFileId, Name};
7
8#[derive(Clone, Debug)]
9pub(super) struct ModDir {
10 /// `.` for `mod.rs`, `lib.rs`
11 /// `./foo` for `foo.rs`
12 /// `./foo/bar` for `mod bar { mod x; }` nested in `foo.rs`
13 path: RelativePathBuf,
14 /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/`
15 root_non_dir_owner: bool,
16}
17
18impl ModDir {
19 pub(super) fn root() -> ModDir {
20 ModDir { path: RelativePathBuf::default(), root_non_dir_owner: false }
21 }
22
23 pub(super) fn descend_into_definition(
24 &self,
25 name: &Name,
26 attr_path: Option<&SmolStr>,
27 ) -> ModDir {
28 let mut path = self.path.clone();
29 match attr_to_path(attr_path) {
30 None => path.push(&name.to_string()),
31 Some(attr_path) => {
32 if self.root_non_dir_owner {
33 assert!(path.pop());
34 }
35 path.push(attr_path);
36 }
37 }
38 ModDir { path, root_non_dir_owner: false }
39 }
40
41 pub(super) fn resolve_declaration(
42 &self,
43 db: &impl DefDatabase,
44 file_id: HirFileId,
45 name: &Name,
46 attr_path: Option<&SmolStr>,
47 ) -> Result<(FileId, ModDir), RelativePathBuf> {
48 let file_id = file_id.original_file(db);
49
50 let mut candidate_files = Vec::new();
51 match attr_to_path(attr_path) {
52 Some(attr_path) => {
53 let base =
54 if self.root_non_dir_owner { self.path.parent().unwrap() } else { &self.path };
55 candidate_files.push(base.join(attr_path))
56 }
57 None => {
58 candidate_files.push(self.path.join(&format!("{}.rs", name)));
59 candidate_files.push(self.path.join(&format!("{}/mod.rs", name)));
60 }
61 };
62
63 for candidate in candidate_files.iter() {
64 if let Some(file_id) = db.resolve_relative_path(file_id, candidate) {
65 let mut root_non_dir_owner = false;
66 let mut mod_path = RelativePathBuf::new();
67 if !(candidate.ends_with("mod.rs") || attr_path.is_some()) {
68 root_non_dir_owner = true;
69 mod_path.push(&name.to_string());
70 }
71 return Ok((file_id, ModDir { path: mod_path, root_non_dir_owner }));
72 }
73 }
74 Err(candidate_files.remove(0))
75 }
76}
77
78fn attr_to_path(attr: Option<&SmolStr>) -> Option<RelativePathBuf> {
79 attr.and_then(|it| RelativePathBuf::from_path(&it.replace("\\", "/")).ok())
80}
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs
deleted file mode 100644
index 0da6789de..000000000
--- a/crates/ra_hir/src/nameres/per_ns.rs
+++ /dev/null
@@ -1,80 +0,0 @@
1//! FIXME: write short doc here
2
3use crate::{MacroDef, ModuleDef};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub enum Namespace {
7 Types,
8 Values,
9 // Note that only type inference uses this enum, and it doesn't care about macros.
10 // Macro,
11}
12
13#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
14pub struct PerNs {
15 pub types: Option<ModuleDef>,
16 pub values: Option<ModuleDef>,
17 /// Since macros has different type, many methods simply ignore it.
18 /// We can only use special method like `get_macros` to access it.
19 pub macros: Option<MacroDef>,
20}
21
22impl Default for PerNs {
23 fn default() -> Self {
24 PerNs { types: None, values: None, macros: None }
25 }
26}
27
28impl PerNs {
29 pub fn none() -> PerNs {
30 PerNs { types: None, values: None, macros: None }
31 }
32
33 pub fn values(t: ModuleDef) -> PerNs {
34 PerNs { types: None, values: Some(t), macros: None }
35 }
36
37 pub fn types(t: ModuleDef) -> PerNs {
38 PerNs { types: Some(t), values: None, macros: None }
39 }
40
41 pub fn both(types: ModuleDef, values: ModuleDef) -> PerNs {
42 PerNs { types: Some(types), values: Some(values), macros: None }
43 }
44
45 pub fn macros(macro_: MacroDef) -> PerNs {
46 PerNs { types: None, values: None, macros: Some(macro_) }
47 }
48
49 pub fn is_none(&self) -> bool {
50 self.types.is_none() && self.values.is_none() && self.macros.is_none()
51 }
52
53 pub fn is_all(&self) -> bool {
54 self.types.is_some() && self.values.is_some() && self.macros.is_some()
55 }
56
57 pub fn take_types(self) -> Option<ModuleDef> {
58 self.types
59 }
60
61 pub fn take_values(self) -> Option<ModuleDef> {
62 self.values
63 }
64
65 pub fn get_macros(&self) -> Option<MacroDef> {
66 self.macros
67 }
68
69 pub fn only_macros(&self) -> PerNs {
70 PerNs { types: None, values: None, macros: self.macros }
71 }
72
73 pub fn or(self, other: PerNs) -> PerNs {
74 PerNs {
75 types: self.types.or(other.types),
76 values: self.values.or(other.values),
77 macros: self.macros.or(other.macros),
78 }
79 }
80}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
deleted file mode 100644
index 8c6b40aaf..000000000
--- a/crates/ra_hir/src/nameres/tests.rs
+++ /dev/null
@@ -1,578 +0,0 @@
1mod macros;
2mod globs;
3mod incremental;
4mod primitives;
5mod mod_resolution;
6
7use std::sync::Arc;
8
9use insta::assert_snapshot;
10use ra_db::SourceDatabase;
11use test_utils::covers;
12
13use crate::{
14 mock::{CrateGraphFixture, MockDatabase},
15 Crate,
16};
17
18use super::*;
19
20fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc<CrateDefMap> {
21 let mut db = MockDatabase::with_files(fixture);
22 if let Some(graph) = graph {
23 db.set_crate_graph_from_fixture(graph);
24 }
25 let crate_id = db.crate_graph().iter().next().unwrap();
26 let krate = Crate { crate_id };
27 db.crate_def_map(krate)
28}
29
30fn render_crate_def_map(map: &CrateDefMap) -> String {
31 let mut buf = String::new();
32 go(&mut buf, map, "\ncrate", map.root);
33 return buf.trim().to_string();
34
35 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) {
36 *buf += path;
37 *buf += "\n";
38
39 let mut entries = map.modules[module]
40 .scope
41 .items
42 .iter()
43 .map(|(name, res)| (name, res.def))
44 .collect::<Vec<_>>();
45 entries.sort_by_key(|(name, _)| *name);
46
47 for (name, res) in entries {
48 *buf += &format!("{}:", name);
49
50 if res.types.is_some() {
51 *buf += " t";
52 }
53 if res.values.is_some() {
54 *buf += " v";
55 }
56 if res.macros.is_some() {
57 *buf += " m";
58 }
59 if res.is_none() {
60 *buf += " _";
61 }
62
63 *buf += "\n";
64 }
65
66 for (name, child) in map.modules[module].children.iter() {
67 let path = path.to_string() + &format!("::{}", name);
68 go(buf, map, &path, *child);
69 }
70 }
71}
72
73fn def_map(fixtute: &str) -> String {
74 let dm = compute_crate_def_map(fixtute, None);
75 render_crate_def_map(&dm)
76}
77
78fn def_map_with_crate_graph(fixture: &str, graph: CrateGraphFixture) -> String {
79 let dm = compute_crate_def_map(fixture, Some(graph));
80 render_crate_def_map(&dm)
81}
82
83#[test]
84fn crate_def_map_smoke_test() {
85 let map = def_map(
86 "
87 //- /lib.rs
88 mod foo;
89 struct S;
90 use crate::foo::bar::E;
91 use self::E::V;
92
93 //- /foo/mod.rs
94 pub mod bar;
95 fn f() {}
96
97 //- /foo/bar.rs
98 pub struct Baz;
99 enum E { V }
100 ",
101 );
102 assert_snapshot!(map, @r###"
103 â‹®crate
104 â‹®E: t
105 â‹®S: t v
106 â‹®V: t v
107 â‹®foo: t
108 â‹®
109 â‹®crate::foo
110 â‹®bar: t
111 â‹®f: v
112 â‹®
113 â‹®crate::foo::bar
114 â‹®Baz: t v
115 â‹®E: t
116 "###)
117}
118
119#[test]
120fn bogus_paths() {
121 covers!(bogus_paths);
122 let map = def_map(
123 "
124 //- /lib.rs
125 mod foo;
126 struct S;
127 use self;
128
129 //- /foo/mod.rs
130 use super;
131 use crate;
132
133 ",
134 );
135 assert_snapshot!(map, @r###"
136 â‹®crate
137 â‹®S: t v
138 â‹®foo: t
139 â‹®
140 â‹®crate::foo
141 "###
142 )
143}
144
145#[test]
146fn use_as() {
147 let map = def_map(
148 "
149 //- /lib.rs
150 mod foo;
151
152 use crate::foo::Baz as Foo;
153
154 //- /foo/mod.rs
155 pub struct Baz;
156 ",
157 );
158 assert_snapshot!(map,
159 @r###"
160 â‹®crate
161 â‹®Foo: t v
162 â‹®foo: t
163 â‹®
164 â‹®crate::foo
165 â‹®Baz: t v
166 "###
167 );
168}
169
170#[test]
171fn use_trees() {
172 let map = def_map(
173 "
174 //- /lib.rs
175 mod foo;
176
177 use crate::foo::bar::{Baz, Quux};
178
179 //- /foo/mod.rs
180 pub mod bar;
181
182 //- /foo/bar.rs
183 pub struct Baz;
184 pub enum Quux {};
185 ",
186 );
187 assert_snapshot!(map, @r###"
188 â‹®crate
189 â‹®Baz: t v
190 â‹®Quux: t
191 â‹®foo: t
192 â‹®
193 â‹®crate::foo
194 â‹®bar: t
195 â‹®
196 â‹®crate::foo::bar
197 â‹®Baz: t v
198 â‹®Quux: t
199 "###);
200}
201
202#[test]
203fn re_exports() {
204 let map = def_map(
205 "
206 //- /lib.rs
207 mod foo;
208
209 use self::foo::Baz;
210
211 //- /foo/mod.rs
212 pub mod bar;
213
214 pub use self::bar::Baz;
215
216 //- /foo/bar.rs
217 pub struct Baz;
218 ",
219 );
220 assert_snapshot!(map, @r###"
221 â‹®crate
222 â‹®Baz: t v
223 â‹®foo: t
224 â‹®
225 â‹®crate::foo
226 â‹®Baz: t v
227 â‹®bar: t
228 â‹®
229 â‹®crate::foo::bar
230 â‹®Baz: t v
231 "###);
232}
233
234#[test]
235fn std_prelude() {
236 covers!(std_prelude);
237 let map = def_map_with_crate_graph(
238 "
239 //- /main.rs
240 use Foo::*;
241
242 //- /lib.rs
243 mod prelude;
244 #[prelude_import]
245 use prelude::*;
246
247 //- /prelude.rs
248 pub enum Foo { Bar, Baz };
249 ",
250 crate_graph! {
251 "main": ("/main.rs", ["test_crate"]),
252 "test_crate": ("/lib.rs", []),
253 },
254 );
255 assert_snapshot!(map, @r###"
256 â‹®crate
257 â‹®Bar: t v
258 â‹®Baz: t v
259 "###);
260}
261
262#[test]
263fn can_import_enum_variant() {
264 covers!(can_import_enum_variant);
265 let map = def_map(
266 "
267 //- /lib.rs
268 enum E { V }
269 use self::E::V;
270 ",
271 );
272 assert_snapshot!(map, @r###"
273 â‹®crate
274 â‹®E: t
275 â‹®V: t v
276 "###
277 );
278}
279
280#[test]
281fn edition_2015_imports() {
282 let map = def_map_with_crate_graph(
283 "
284 //- /main.rs
285 mod foo;
286 mod bar;
287
288 //- /bar.rs
289 struct Bar;
290
291 //- /foo.rs
292 use bar::Bar;
293 use other_crate::FromLib;
294
295 //- /lib.rs
296 struct FromLib;
297 ",
298 crate_graph! {
299 "main": ("/main.rs", "2015", ["other_crate"]),
300 "other_crate": ("/lib.rs", "2018", []),
301 },
302 );
303
304 assert_snapshot!(map, @r###"
305 â‹®crate
306 â‹®bar: t
307 â‹®foo: t
308 â‹®
309 â‹®crate::bar
310 â‹®Bar: t v
311 â‹®
312 â‹®crate::foo
313 â‹®Bar: t v
314 â‹®FromLib: t v
315 "###);
316}
317
318#[test]
319fn item_map_using_self() {
320 let map = def_map(
321 "
322 //- /lib.rs
323 mod foo;
324 use crate::foo::bar::Baz::{self};
325 //- /foo/mod.rs
326 pub mod bar;
327 //- /foo/bar.rs
328 pub struct Baz;
329 ",
330 );
331 assert_snapshot!(map, @r###"
332 â‹®crate
333 â‹®Baz: t v
334 â‹®foo: t
335 â‹®
336 â‹®crate::foo
337 â‹®bar: t
338 â‹®
339 â‹®crate::foo::bar
340 â‹®Baz: t v
341 "###);
342}
343
344#[test]
345fn item_map_across_crates() {
346 let map = def_map_with_crate_graph(
347 "
348 //- /main.rs
349 use test_crate::Baz;
350
351 //- /lib.rs
352 pub struct Baz;
353 ",
354 crate_graph! {
355 "main": ("/main.rs", ["test_crate"]),
356 "test_crate": ("/lib.rs", []),
357 },
358 );
359
360 assert_snapshot!(map, @r###"
361 â‹®crate
362 â‹®Baz: t v
363 "###);
364}
365
366#[test]
367fn extern_crate_rename() {
368 let map = def_map_with_crate_graph(
369 "
370 //- /main.rs
371 extern crate alloc as alloc_crate;
372
373 mod alloc;
374 mod sync;
375
376 //- /sync.rs
377 use alloc_crate::Arc;
378
379 //- /lib.rs
380 struct Arc;
381 ",
382 crate_graph! {
383 "main": ("/main.rs", ["alloc"]),
384 "alloc": ("/lib.rs", []),
385 },
386 );
387
388 assert_snapshot!(map, @r###"
389 â‹®crate
390 â‹®alloc_crate: t
391 â‹®sync: t
392 â‹®
393 â‹®crate::sync
394 â‹®Arc: t v
395 "###);
396}
397
398#[test]
399fn extern_crate_rename_2015_edition() {
400 let map = def_map_with_crate_graph(
401 "
402 //- /main.rs
403 extern crate alloc as alloc_crate;
404
405 mod alloc;
406 mod sync;
407
408 //- /sync.rs
409 use alloc_crate::Arc;
410
411 //- /lib.rs
412 struct Arc;
413 ",
414 crate_graph! {
415 "main": ("/main.rs", "2015", ["alloc"]),
416 "alloc": ("/lib.rs", []),
417 },
418 );
419
420 assert_snapshot!(map,
421 @r###"
422 â‹®crate
423 â‹®alloc_crate: t
424 â‹®sync: t
425 â‹®
426 â‹®crate::sync
427 â‹®Arc: t v
428 "###
429 );
430}
431
432#[test]
433fn import_across_source_roots() {
434 let map = def_map_with_crate_graph(
435 "
436 //- /lib.rs
437 pub mod a {
438 pub mod b {
439 pub struct C;
440 }
441 }
442
443 //- root /main/
444
445 //- /main/main.rs
446 use test_crate::a::b::C;
447 ",
448 crate_graph! {
449 "main": ("/main/main.rs", ["test_crate"]),
450 "test_crate": ("/lib.rs", []),
451 },
452 );
453
454 assert_snapshot!(map, @r###"
455 â‹®crate
456 â‹®C: t v
457 "###);
458}
459
460#[test]
461fn reexport_across_crates() {
462 let map = def_map_with_crate_graph(
463 "
464 //- /main.rs
465 use test_crate::Baz;
466
467 //- /lib.rs
468 pub use foo::Baz;
469
470 mod foo;
471
472 //- /foo.rs
473 pub struct Baz;
474 ",
475 crate_graph! {
476 "main": ("/main.rs", ["test_crate"]),
477 "test_crate": ("/lib.rs", []),
478 },
479 );
480
481 assert_snapshot!(map, @r###"
482 â‹®crate
483 â‹®Baz: t v
484 "###);
485}
486
487#[test]
488fn values_dont_shadow_extern_crates() {
489 let map = def_map_with_crate_graph(
490 "
491 //- /main.rs
492 fn foo() {}
493 use foo::Bar;
494
495 //- /foo/lib.rs
496 pub struct Bar;
497 ",
498 crate_graph! {
499 "main": ("/main.rs", ["foo"]),
500 "foo": ("/foo/lib.rs", []),
501 },
502 );
503
504 assert_snapshot!(map, @r###"
505 â‹®crate
506 â‹®Bar: t v
507 â‹®foo: v
508 "###);
509}
510
511#[test]
512fn cfg_not_test() {
513 let map = def_map_with_crate_graph(
514 r#"
515 //- /main.rs
516 use {Foo, Bar, Baz};
517 //- /lib.rs
518 #[prelude_import]
519 pub use self::prelude::*;
520 mod prelude {
521 #[cfg(test)]
522 pub struct Foo;
523 #[cfg(not(test))]
524 pub struct Bar;
525 #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
526 pub struct Baz;
527 }
528 "#,
529 crate_graph! {
530 "main": ("/main.rs", ["std"]),
531 "std": ("/lib.rs", []),
532 },
533 );
534
535 assert_snapshot!(map, @r###"
536 â‹®crate
537 â‹®Bar: t v
538 â‹®Baz: _
539 â‹®Foo: _
540 "###);
541}
542
543#[test]
544fn cfg_test() {
545 let map = def_map_with_crate_graph(
546 r#"
547 //- /main.rs
548 use {Foo, Bar, Baz};
549 //- /lib.rs
550 #[prelude_import]
551 pub use self::prelude::*;
552 mod prelude {
553 #[cfg(test)]
554 pub struct Foo;
555 #[cfg(not(test))]
556 pub struct Bar;
557 #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
558 pub struct Baz;
559 }
560 "#,
561 crate_graph! {
562 "main": ("/main.rs", ["std"]),
563 "std": ("/lib.rs", [], cfg = {
564 "test",
565 "feature" = "foo",
566 "feature" = "bar",
567 "opt" = "42",
568 }),
569 },
570 );
571
572 assert_snapshot!(map, @r###"
573 â‹®crate
574 â‹®Bar: _
575 â‹®Baz: t v
576 â‹®Foo: t v
577 "###);
578}
diff --git a/crates/ra_hir/src/nameres/tests/globs.rs b/crates/ra_hir/src/nameres/tests/globs.rs
deleted file mode 100644
index 7ac22b47b..000000000
--- a/crates/ra_hir/src/nameres/tests/globs.rs
+++ /dev/null
@@ -1,118 +0,0 @@
1use super::*;
2
3#[test]
4fn glob_1() {
5 let map = def_map(
6 "
7 //- /lib.rs
8 mod foo;
9 use foo::*;
10
11 //- /foo/mod.rs
12 pub mod bar;
13 pub use self::bar::Baz;
14 pub struct Foo;
15
16 //- /foo/bar.rs
17 pub struct Baz;
18 ",
19 );
20 assert_snapshot!(map, @r###"
21 â‹®crate
22 â‹®Baz: t v
23 â‹®Foo: t v
24 â‹®bar: t
25 â‹®foo: t
26 â‹®
27 â‹®crate::foo
28 â‹®Baz: t v
29 â‹®Foo: t v
30 â‹®bar: t
31 â‹®
32 â‹®crate::foo::bar
33 â‹®Baz: t v
34 "###
35 );
36}
37
38#[test]
39fn glob_2() {
40 let map = def_map(
41 "
42 //- /lib.rs
43 mod foo;
44 use foo::*;
45
46 //- /foo/mod.rs
47 pub mod bar;
48 pub use self::bar::*;
49 pub struct Foo;
50
51 //- /foo/bar.rs
52 pub struct Baz;
53 pub use super::*;
54 ",
55 );
56 assert_snapshot!(map, @r###"
57 â‹®crate
58 â‹®Baz: t v
59 â‹®Foo: t v
60 â‹®bar: t
61 â‹®foo: t
62 â‹®
63 â‹®crate::foo
64 â‹®Baz: t v
65 â‹®Foo: t v
66 â‹®bar: t
67 â‹®
68 â‹®crate::foo::bar
69 â‹®Baz: t v
70 â‹®Foo: t v
71 â‹®bar: t
72 "###
73 );
74}
75
76#[test]
77fn glob_across_crates() {
78 covers!(glob_across_crates);
79 let map = def_map_with_crate_graph(
80 "
81 //- /main.rs
82 use test_crate::*;
83
84 //- /lib.rs
85 pub struct Baz;
86 ",
87 crate_graph! {
88 "main": ("/main.rs", ["test_crate"]),
89 "test_crate": ("/lib.rs", []),
90 },
91 );
92 assert_snapshot!(map, @r###"
93 â‹®crate
94 â‹®Baz: t v
95 "###
96 );
97}
98
99#[test]
100fn glob_enum() {
101 covers!(glob_enum);
102 let map = def_map(
103 "
104 //- /lib.rs
105 enum Foo {
106 Bar, Baz
107 }
108 use self::Foo::*;
109 ",
110 );
111 assert_snapshot!(map, @r###"
112 â‹®crate
113 â‹®Bar: t v
114 â‹®Baz: t v
115 â‹®Foo: t
116 "###
117 );
118}
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
deleted file mode 100644
index af9c39760..000000000
--- a/crates/ra_hir/src/nameres/tests/incremental.rs
+++ /dev/null
@@ -1,141 +0,0 @@
1use super::*;
2
3use std::sync::Arc;
4
5use ra_db::{SourceDatabase, SourceDatabaseExt};
6
7fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) {
8 let (mut db, pos) = MockDatabase::with_position(initial);
9 let crate_id = db.crate_graph().iter().next().unwrap();
10 let krate = Crate { crate_id };
11 {
12 let events = db.log_executed(|| {
13 db.crate_def_map(krate);
14 });
15 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
16 }
17 db.set_file_text(pos.file_id, Arc::new(file_change.to_string()));
18
19 {
20 let events = db.log_executed(|| {
21 db.crate_def_map(krate);
22 });
23 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
24 }
25}
26
27#[test]
28fn typing_inside_a_function_should_not_invalidate_def_map() {
29 check_def_map_is_not_recomputed(
30 "
31 //- /lib.rs
32 mod foo;<|>
33
34 use crate::foo::bar::Baz;
35
36 fn foo() -> i32 {
37 1 + 1
38 }
39 //- /foo/mod.rs
40 pub mod bar;
41
42 //- /foo/bar.rs
43 pub struct Baz;
44 ",
45 "
46 mod foo;
47
48 use crate::foo::bar::Baz;
49
50 fn foo() -> i32 { 92 }
51 ",
52 );
53}
54
55#[test]
56fn adding_inner_items_should_not_invalidate_def_map() {
57 check_def_map_is_not_recomputed(
58 "
59 //- /lib.rs
60 struct S { a: i32}
61 enum E { A }
62 trait T {
63 fn a() {}
64 }
65 mod foo;<|>
66 impl S {
67 fn a() {}
68 }
69 use crate::foo::bar::Baz;
70 //- /foo/mod.rs
71 pub mod bar;
72
73 //- /foo/bar.rs
74 pub struct Baz;
75 ",
76 "
77 struct S { a: i32, b: () }
78 enum E { A, B }
79 trait T {
80 fn a() {}
81 fn b() {}
82 }
83 mod foo;<|>
84 impl S {
85 fn a() {}
86 fn b() {}
87 }
88 use crate::foo::bar::Baz;
89 ",
90 );
91}
92
93#[test]
94fn typing_inside_a_macro_should_not_invalidate_def_map() {
95 let (mut db, pos) = MockDatabase::with_position(
96 "
97 //- /lib.rs
98 macro_rules! m {
99 ($ident:ident) => {
100 fn f() {
101 $ident + $ident;
102 };
103 }
104 }
105 mod foo;
106
107 //- /foo/mod.rs
108 pub mod bar;
109
110 //- /foo/bar.rs
111 <|>
112 m!(X);
113 ",
114 );
115 {
116 let events = db.log_executed(|| {
117 let src = crate::Source {
118 file_id: pos.file_id.into(),
119 ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
120 };
121 let module = crate::Module::from_definition(&db, src).unwrap();
122 let decls = module.declarations(&db);
123 assert_eq!(decls.len(), 18);
124 });
125 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
126 }
127 db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));
128
129 {
130 let events = db.log_executed(|| {
131 let src = crate::Source {
132 file_id: pos.file_id.into(),
133 ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
134 };
135 let module = crate::Module::from_definition(&db, src).unwrap();
136 let decls = module.declarations(&db);
137 assert_eq!(decls.len(), 18);
138 });
139 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
140 }
141}
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
deleted file mode 100644
index 4f52ad2c5..000000000
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ /dev/null
@@ -1,635 +0,0 @@
1use super::*;
2
3#[test]
4fn macro_rules_are_globally_visible() {
5 let map = def_map(
6 "
7 //- /lib.rs
8 macro_rules! structs {
9 ($($i:ident),*) => {
10 $(struct $i { field: u32 } )*
11 }
12 }
13 structs!(Foo);
14 mod nested;
15
16 //- /nested.rs
17 structs!(Bar, Baz);
18 ",
19 );
20 assert_snapshot!(map, @r###"
21 â‹®crate
22 â‹®Foo: t v
23 â‹®nested: t
24 â‹®
25 â‹®crate::nested
26 â‹®Bar: t v
27 â‹®Baz: t v
28 "###);
29}
30
31#[test]
32fn macro_rules_can_define_modules() {
33 let map = def_map(
34 "
35 //- /lib.rs
36 macro_rules! m {
37 ($name:ident) => { mod $name; }
38 }
39 m!(n1);
40
41 mod m {
42 m!(n3)
43 }
44
45 //- /n1.rs
46 m!(n2)
47 //- /n1/n2.rs
48 struct X;
49 //- /m/n3.rs
50 struct Y;
51 ",
52 );
53 assert_snapshot!(map, @r###"
54 crate
55 m: t
56 n1: t
57
58 crate::m
59 n3: t
60
61 crate::m::n3
62 Y: t v
63
64 crate::n1
65 n2: t
66
67 crate::n1::n2
68 X: t v
69 "###);
70}
71
72#[test]
73fn macro_rules_from_other_crates_are_visible() {
74 let map = def_map_with_crate_graph(
75 "
76 //- /main.rs
77 foo::structs!(Foo, Bar)
78 mod bar;
79
80 //- /bar.rs
81 use crate::*;
82
83 //- /lib.rs
84 #[macro_export]
85 macro_rules! structs {
86 ($($i:ident),*) => {
87 $(struct $i { field: u32 } )*
88 }
89 }
90 ",
91 crate_graph! {
92 "main": ("/main.rs", ["foo"]),
93 "foo": ("/lib.rs", []),
94 },
95 );
96 assert_snapshot!(map, @r###"
97 â‹®crate
98 â‹®Bar: t v
99 â‹®Foo: t v
100 â‹®bar: t
101 â‹®
102 â‹®crate::bar
103 â‹®Bar: t v
104 â‹®Foo: t v
105 â‹®bar: t
106 "###);
107}
108
109#[test]
110fn macro_rules_export_with_local_inner_macros_are_visible() {
111 let map = def_map_with_crate_graph(
112 "
113 //- /main.rs
114 foo::structs!(Foo, Bar)
115 mod bar;
116
117 //- /bar.rs
118 use crate::*;
119
120 //- /lib.rs
121 #[macro_export(local_inner_macros)]
122 macro_rules! structs {
123 ($($i:ident),*) => {
124 $(struct $i { field: u32 } )*
125 }
126 }
127 ",
128 crate_graph! {
129 "main": ("/main.rs", ["foo"]),
130 "foo": ("/lib.rs", []),
131 },
132 );
133 assert_snapshot!(map, @r###"
134 â‹®crate
135 â‹®Bar: t v
136 â‹®Foo: t v
137 â‹®bar: t
138 â‹®
139 â‹®crate::bar
140 â‹®Bar: t v
141 â‹®Foo: t v
142 â‹®bar: t
143 "###);
144}
145
146#[test]
147fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
148 let map = def_map_with_crate_graph(
149 "
150 //- /main.rs
151 macro_rules! baz {
152 () => {
153 use foo::bar;
154 }
155 }
156
157 foo!();
158 bar!();
159 baz!();
160
161 //- /lib.rs
162 #[macro_export]
163 macro_rules! foo {
164 () => {
165 struct Foo { field: u32 }
166 }
167 }
168 #[macro_export]
169 macro_rules! bar {
170 () => {
171 use foo::foo;
172 }
173 }
174 ",
175 crate_graph! {
176 "main": ("/main.rs", ["foo"]),
177 "foo": ("/lib.rs", []),
178 },
179 );
180 assert_snapshot!(map, @r###"
181 â‹®crate
182 â‹®Foo: t v
183 â‹®bar: m
184 â‹®foo: m
185 "###);
186}
187
188#[test]
189fn macro_rules_from_other_crates_are_visible_with_macro_use() {
190 covers!(macro_rules_from_other_crates_are_visible_with_macro_use);
191 let map = def_map_with_crate_graph(
192 "
193 //- /main.rs
194 structs!(Foo);
195 structs_priv!(Bar);
196 structs_not_exported!(MacroNotResolved1);
197 crate::structs!(MacroNotResolved2);
198
199 mod bar;
200
201 #[macro_use]
202 extern crate foo;
203
204 //- /bar.rs
205 structs!(Baz);
206 crate::structs!(MacroNotResolved3);
207
208 //- /lib.rs
209 #[macro_export]
210 macro_rules! structs {
211 ($i:ident) => { struct $i; }
212 }
213
214 macro_rules! structs_not_exported {
215 ($i:ident) => { struct $i; }
216 }
217
218 mod priv_mod {
219 #[macro_export]
220 macro_rules! structs_priv {
221 ($i:ident) => { struct $i; }
222 }
223 }
224 ",
225 crate_graph! {
226 "main": ("/main.rs", ["foo"]),
227 "foo": ("/lib.rs", []),
228 },
229 );
230 assert_snapshot!(map, @r###"
231 â‹®crate
232 â‹®Bar: t v
233 â‹®Foo: t v
234 â‹®bar: t
235 â‹®foo: t
236 â‹®
237 â‹®crate::bar
238 â‹®Baz: t v
239 "###);
240}
241
242#[test]
243fn prelude_is_macro_use() {
244 covers!(prelude_is_macro_use);
245 let map = def_map_with_crate_graph(
246 "
247 //- /main.rs
248 structs!(Foo);
249 structs_priv!(Bar);
250 structs_outside!(Out);
251 crate::structs!(MacroNotResolved2);
252
253 mod bar;
254
255 //- /bar.rs
256 structs!(Baz);
257 crate::structs!(MacroNotResolved3);
258
259 //- /lib.rs
260 #[prelude_import]
261 use self::prelude::*;
262
263 mod prelude {
264 #[macro_export]
265 macro_rules! structs {
266 ($i:ident) => { struct $i; }
267 }
268
269 mod priv_mod {
270 #[macro_export]
271 macro_rules! structs_priv {
272 ($i:ident) => { struct $i; }
273 }
274 }
275 }
276
277 #[macro_export]
278 macro_rules! structs_outside {
279 ($i:ident) => { struct $i; }
280 }
281 ",
282 crate_graph! {
283 "main": ("/main.rs", ["foo"]),
284 "foo": ("/lib.rs", []),
285 },
286 );
287 assert_snapshot!(map, @r###"
288 â‹®crate
289 â‹®Bar: t v
290 â‹®Foo: t v
291 â‹®Out: t v
292 â‹®bar: t
293 â‹®
294 â‹®crate::bar
295 â‹®Baz: t v
296 "###);
297}
298
299#[test]
300fn prelude_cycle() {
301 let map = def_map(
302 "
303 //- /lib.rs
304 #[prelude_import]
305 use self::prelude::*;
306
307 declare_mod!();
308
309 mod prelude {
310 macro_rules! declare_mod {
311 () => (mod foo {})
312 }
313 }
314 ",
315 );
316 assert_snapshot!(map, @r###"
317 â‹®crate
318 â‹®prelude: t
319 â‹®
320 â‹®crate::prelude
321 "###);
322}
323
324#[test]
325fn plain_macros_are_legacy_textual_scoped() {
326 let map = def_map(
327 r#"
328 //- /main.rs
329 mod m1;
330 bar!(NotFoundNotMacroUse);
331
332 mod m2 {
333 foo!(NotFoundBeforeInside2);
334 }
335
336 macro_rules! foo {
337 ($x:ident) => { struct $x; }
338 }
339 foo!(Ok);
340
341 mod m3;
342 foo!(OkShadowStop);
343 bar!(NotFoundMacroUseStop);
344
345 #[macro_use]
346 mod m5 {
347 #[macro_use]
348 mod m6 {
349 macro_rules! foo {
350 ($x:ident) => { fn $x() {} }
351 }
352 }
353 }
354 foo!(ok_double_macro_use_shadow);
355
356 baz!(NotFoundBefore);
357 #[macro_use]
358 mod m7 {
359 macro_rules! baz {
360 ($x:ident) => { struct $x; }
361 }
362 }
363 baz!(OkAfter);
364
365 //- /m1.rs
366 foo!(NotFoundBeforeInside1);
367 macro_rules! bar {
368 ($x:ident) => { struct $x; }
369 }
370
371 //- /m3/mod.rs
372 foo!(OkAfterInside);
373 macro_rules! foo {
374 ($x:ident) => { fn $x() {} }
375 }
376 foo!(ok_shadow);
377
378 #[macro_use]
379 mod m4;
380 bar!(OkMacroUse);
381
382 //- /m3/m4.rs
383 foo!(ok_shadow_deep);
384 macro_rules! bar {
385 ($x:ident) => { struct $x; }
386 }
387 "#,
388 );
389 assert_snapshot!(map, @r###"
390 â‹®crate
391 â‹®Ok: t v
392 â‹®OkAfter: t v
393 â‹®OkShadowStop: t v
394 â‹®m1: t
395 â‹®m2: t
396 â‹®m3: t
397 â‹®m5: t
398 â‹®m7: t
399 â‹®ok_double_macro_use_shadow: v
400 â‹®
401 â‹®crate::m7
402 â‹®
403 â‹®crate::m1
404 â‹®
405 â‹®crate::m5
406 â‹®m6: t
407 â‹®
408 â‹®crate::m5::m6
409 â‹®
410 â‹®crate::m2
411 â‹®
412 â‹®crate::m3
413 â‹®OkAfterInside: t v
414 â‹®OkMacroUse: t v
415 â‹®m4: t
416 â‹®ok_shadow: v
417 â‹®
418 â‹®crate::m3::m4
419 â‹®ok_shadow_deep: v
420 "###);
421}
422
423#[test]
424fn type_value_macro_live_in_different_scopes() {
425 let map = def_map(
426 "
427 //- /main.rs
428 #[macro_export]
429 macro_rules! foo {
430 ($x:ident) => { type $x = (); }
431 }
432
433 foo!(foo);
434 use foo as bar;
435
436 use self::foo as baz;
437 fn baz() {}
438 ",
439 );
440 assert_snapshot!(map, @r###"
441 â‹®crate
442 â‹®bar: t m
443 â‹®baz: t v m
444 â‹®foo: t m
445 "###);
446}
447
448#[test]
449fn macro_use_can_be_aliased() {
450 let map = def_map_with_crate_graph(
451 "
452 //- /main.rs
453 #[macro_use]
454 extern crate foo;
455
456 foo!(Direct);
457 bar!(Alias);
458
459 //- /lib.rs
460 use crate::foo as bar;
461
462 mod m {
463 #[macro_export]
464 macro_rules! foo {
465 ($x:ident) => { struct $x; }
466 }
467 }
468 ",
469 crate_graph! {
470 "main": ("/main.rs", ["foo"]),
471 "foo": ("/lib.rs", []),
472 },
473 );
474 assert_snapshot!(map, @r###"
475 â‹®crate
476 â‹®Alias: t v
477 â‹®Direct: t v
478 â‹®foo: t
479 "###);
480}
481
482#[test]
483fn path_qualified_macros() {
484 let map = def_map(
485 "
486 //- /main.rs
487 macro_rules! foo {
488 ($x:ident) => { struct $x; }
489 }
490
491 crate::foo!(NotResolved);
492
493 crate::bar!(OkCrate);
494 bar!(OkPlain);
495 alias1!(NotHere);
496 m::alias1!(OkAliasPlain);
497 m::alias2!(OkAliasSuper);
498 m::alias3!(OkAliasCrate);
499 not_found!(NotFound);
500
501 mod m {
502 #[macro_export]
503 macro_rules! bar {
504 ($x:ident) => { struct $x; }
505 }
506
507 pub use bar as alias1;
508 pub use super::bar as alias2;
509 pub use crate::bar as alias3;
510 pub use self::bar as not_found;
511 }
512 ",
513 );
514 assert_snapshot!(map, @r###"
515 â‹®crate
516 â‹®OkAliasCrate: t v
517 â‹®OkAliasPlain: t v
518 â‹®OkAliasSuper: t v
519 â‹®OkCrate: t v
520 â‹®OkPlain: t v
521 â‹®bar: m
522 â‹®m: t
523 â‹®
524 â‹®crate::m
525 â‹®alias1: m
526 â‹®alias2: m
527 â‹®alias3: m
528 â‹®not_found: _
529 "###);
530}
531
532#[test]
533fn macro_dollar_crate_is_correct_in_item() {
534 covers!(macro_dollar_crate_self);
535 covers!(macro_dollar_crate_other);
536 let map = def_map_with_crate_graph(
537 "
538 //- /main.rs
539 #[macro_use]
540 extern crate foo;
541
542 #[macro_use]
543 mod m {
544 macro_rules! current {
545 () => {
546 use $crate::Foo as FooSelf;
547 }
548 }
549 }
550
551 struct Foo;
552
553 current!();
554 not_current1!();
555 foo::not_current2!();
556
557 //- /lib.rs
558 mod m {
559 #[macro_export]
560 macro_rules! not_current1 {
561 () => {
562 use $crate::Bar;
563 }
564 }
565 }
566
567 #[macro_export]
568 macro_rules! not_current2 {
569 () => {
570 use $crate::Baz;
571 }
572 }
573
574 struct Bar;
575 struct Baz;
576 ",
577 crate_graph! {
578 "main": ("/main.rs", ["foo"]),
579 "foo": ("/lib.rs", []),
580 },
581 );
582 assert_snapshot!(map, @r###"
583 â‹®crate
584 â‹®Bar: t v
585 â‹®Baz: t v
586 â‹®Foo: t v
587 â‹®FooSelf: t v
588 â‹®foo: t
589 â‹®m: t
590 â‹®
591 â‹®crate::m
592 "###);
593}
594
595#[test]
596fn macro_dollar_crate_is_correct_in_indirect_deps() {
597 covers!(macro_dollar_crate_other);
598 // From std
599 let map = def_map_with_crate_graph(
600 r#"
601 //- /main.rs
602 foo!();
603
604 //- /std.rs
605 #[prelude_import]
606 use self::prelude::*;
607
608 pub use core::foo;
609
610 mod prelude {}
611
612 #[macro_use]
613 mod std_macros;
614
615 //- /core.rs
616 #[macro_export]
617 macro_rules! foo {
618 () => {
619 use $crate::bar;
620 }
621 }
622
623 pub struct bar;
624 "#,
625 crate_graph! {
626 "main": ("/main.rs", ["std"]),
627 "std": ("/std.rs", ["core"]),
628 "core": ("/core.rs", []),
629 },
630 );
631 assert_snapshot!(map, @r###"
632 â‹®crate
633 â‹®bar: t v
634 "###);
635}
diff --git a/crates/ra_hir/src/nameres/tests/mod_resolution.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
deleted file mode 100644
index abfe8b1c3..000000000
--- a/crates/ra_hir/src/nameres/tests/mod_resolution.rs
+++ /dev/null
@@ -1,759 +0,0 @@
1use super::*;
2
3#[test]
4fn name_res_works_for_broken_modules() {
5 // covers!(name_res_works_for_broken_modules);
6 let map = def_map(
7 "
8 //- /lib.rs
9 mod foo // no `;`, no body
10
11 use self::foo::Baz;
12
13 //- /foo/mod.rs
14 pub mod bar;
15
16 pub use self::bar::Baz;
17
18 //- /foo/bar.rs
19 pub struct Baz;
20 ",
21 );
22 assert_snapshot!(map, @r###"
23 â‹®crate
24 â‹®Baz: _
25 "###);
26}
27
28#[test]
29fn nested_module_resolution() {
30 let map = def_map(
31 "
32 //- /lib.rs
33 mod n1;
34
35 //- /n1.rs
36 mod n2;
37
38 //- /n1/n2.rs
39 struct X;
40 ",
41 );
42
43 assert_snapshot!(map, @r###"
44 â‹®crate
45 â‹®n1: t
46 â‹®
47 â‹®crate::n1
48 â‹®n2: t
49 â‹®
50 â‹®crate::n1::n2
51 â‹®X: t v
52 "###);
53}
54
55#[test]
56fn module_resolution_works_for_non_standard_filenames() {
57 let map = def_map_with_crate_graph(
58 "
59 //- /my_library.rs
60 mod foo;
61 use self::foo::Bar;
62
63 //- /foo/mod.rs
64 pub struct Bar;
65 ",
66 crate_graph! {
67 "my_library": ("/my_library.rs", []),
68 },
69 );
70
71 assert_snapshot!(map, @r###"
72 â‹®crate
73 â‹®Bar: t v
74 â‹®foo: t
75 â‹®
76 â‹®crate::foo
77 â‹®Bar: t v
78 "###);
79}
80
81#[test]
82fn module_resolution_works_for_raw_modules() {
83 let map = def_map(
84 "
85 //- /lib.rs
86 mod r#async;
87 use self::r#async::Bar;
88
89 //- /async.rs
90 pub struct Bar;
91 ",
92 );
93
94 assert_snapshot!(map, @r###"
95 â‹®crate
96 â‹®Bar: t v
97 â‹®async: t
98 â‹®
99 â‹®crate::async
100 â‹®Bar: t v
101 "###);
102}
103
104#[test]
105fn module_resolution_decl_path() {
106 let map = def_map(
107 r###"
108 //- /lib.rs
109 #[path = "bar/baz/foo.rs"]
110 mod foo;
111 use self::foo::Bar;
112
113 //- /bar/baz/foo.rs
114 pub struct Bar;
115 "###,
116 );
117
118 assert_snapshot!(map, @r###"
119 â‹®crate
120 â‹®Bar: t v
121 â‹®foo: t
122 â‹®
123 â‹®crate::foo
124 â‹®Bar: t v
125 "###);
126}
127
128#[test]
129fn module_resolution_module_with_path_in_mod_rs() {
130 let map = def_map(
131 r###"
132 //- /main.rs
133 mod foo;
134
135 //- /foo/mod.rs
136 #[path = "baz.rs"]
137 pub mod bar;
138
139 use self::bar::Baz;
140
141 //- /foo/baz.rs
142 pub struct Baz;
143 "###,
144 );
145
146 assert_snapshot!(map, @r###"
147 â‹®crate
148 â‹®foo: t
149 â‹®
150 â‹®crate::foo
151 â‹®Baz: t v
152 â‹®bar: t
153 â‹®
154 â‹®crate::foo::bar
155 â‹®Baz: t v
156 "###);
157}
158
159#[test]
160fn module_resolution_module_with_path_non_crate_root() {
161 let map = def_map(
162 r###"
163 //- /main.rs
164 mod foo;
165
166 //- /foo.rs
167 #[path = "baz.rs"]
168 pub mod bar;
169
170 use self::bar::Baz;
171
172 //- /baz.rs
173 pub struct Baz;
174 "###,
175 );
176
177 assert_snapshot!(map, @r###"
178 â‹®crate
179 â‹®foo: t
180 â‹®
181 â‹®crate::foo
182 â‹®Baz: t v
183 â‹®bar: t
184 â‹®
185 â‹®crate::foo::bar
186 â‹®Baz: t v
187 "###);
188}
189
190#[test]
191fn module_resolution_module_decl_path_super() {
192 let map = def_map(
193 r###"
194 //- /main.rs
195 #[path = "bar/baz/module.rs"]
196 mod foo;
197 pub struct Baz;
198
199 //- /bar/baz/module.rs
200 use super::Baz;
201 "###,
202 );
203
204 assert_snapshot!(map, @r###"
205 â‹®crate
206 â‹®Baz: t v
207 â‹®foo: t
208 â‹®
209 â‹®crate::foo
210 â‹®Baz: t v
211 "###);
212}
213
214#[test]
215fn module_resolution_explicit_path_mod_rs() {
216 let map = def_map(
217 r###"
218 //- /main.rs
219 #[path = "module/mod.rs"]
220 mod foo;
221
222 //- /module/mod.rs
223 pub struct Baz;
224 "###,
225 );
226
227 assert_snapshot!(map, @r###"
228 â‹®crate
229 â‹®foo: t
230 â‹®
231 â‹®crate::foo
232 â‹®Baz: t v
233 "###);
234}
235
236#[test]
237fn module_resolution_relative_path() {
238 let map = def_map(
239 r###"
240 //- /main.rs
241 mod foo;
242
243 //- /foo.rs
244 #[path = "./sub.rs"]
245 pub mod foo_bar;
246
247 //- /sub.rs
248 pub struct Baz;
249 "###,
250 );
251
252 assert_snapshot!(map, @r###"
253 â‹®crate
254 â‹®foo: t
255 â‹®
256 â‹®crate::foo
257 â‹®foo_bar: t
258 â‹®
259 â‹®crate::foo::foo_bar
260 â‹®Baz: t v
261 "###);
262}
263
264#[test]
265fn module_resolution_relative_path_2() {
266 let map = def_map(
267 r###"
268 //- /main.rs
269 mod foo;
270
271 //- /foo/mod.rs
272 #[path="../sub.rs"]
273 pub mod foo_bar;
274
275 //- /sub.rs
276 pub struct Baz;
277 "###,
278 );
279
280 assert_snapshot!(map, @r###"
281 â‹®crate
282 â‹®foo: t
283 â‹®
284 â‹®crate::foo
285 â‹®foo_bar: t
286 â‹®
287 â‹®crate::foo::foo_bar
288 â‹®Baz: t v
289 "###);
290}
291
292#[test]
293fn module_resolution_explicit_path_mod_rs_2() {
294 let map = def_map(
295 r###"
296 //- /main.rs
297 #[path = "module/bar/mod.rs"]
298 mod foo;
299
300 //- /module/bar/mod.rs
301 pub struct Baz;
302 "###,
303 );
304
305 assert_snapshot!(map, @r###"
306 â‹®crate
307 â‹®foo: t
308 â‹®
309 â‹®crate::foo
310 â‹®Baz: t v
311 "###);
312}
313
314#[test]
315fn module_resolution_explicit_path_mod_rs_with_win_separator() {
316 let map = def_map(
317 r###"
318 //- /main.rs
319 #[path = "module\bar\mod.rs"]
320 mod foo;
321
322 //- /module/bar/mod.rs
323 pub struct Baz;
324 "###,
325 );
326
327 assert_snapshot!(map, @r###"
328 â‹®crate
329 â‹®foo: t
330 â‹®
331 â‹®crate::foo
332 â‹®Baz: t v
333 "###);
334}
335
336#[test]
337fn module_resolution_decl_inside_inline_module_with_path_attribute() {
338 let map = def_map(
339 r###"
340 //- /main.rs
341 #[path = "models"]
342 mod foo {
343 mod bar;
344 }
345
346 //- /models/bar.rs
347 pub struct Baz;
348 "###,
349 );
350
351 assert_snapshot!(map, @r###"
352 â‹®crate
353 â‹®foo: t
354 â‹®
355 â‹®crate::foo
356 â‹®bar: t
357 â‹®
358 â‹®crate::foo::bar
359 â‹®Baz: t v
360 "###);
361}
362
363#[test]
364fn module_resolution_decl_inside_inline_module() {
365 let map = def_map(
366 r###"
367 //- /main.rs
368 mod foo {
369 mod bar;
370 }
371
372 //- /foo/bar.rs
373 pub struct Baz;
374 "###,
375 );
376
377 assert_snapshot!(map, @r###"
378 â‹®crate
379 â‹®foo: t
380 â‹®
381 â‹®crate::foo
382 â‹®bar: t
383 â‹®
384 â‹®crate::foo::bar
385 â‹®Baz: t v
386 "###);
387}
388
389#[test]
390fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
391 let map = def_map(
392 r###"
393 //- /main.rs
394 #[path = "models/db"]
395 mod foo {
396 mod bar;
397 }
398
399 //- /models/db/bar.rs
400 pub struct Baz;
401 "###,
402 );
403
404 assert_snapshot!(map, @r###"
405 â‹®crate
406 â‹®foo: t
407 â‹®
408 â‹®crate::foo
409 â‹®bar: t
410 â‹®
411 â‹®crate::foo::bar
412 â‹®Baz: t v
413 "###);
414}
415
416#[test]
417fn module_resolution_decl_inside_inline_module_3() {
418 let map = def_map(
419 r###"
420 //- /main.rs
421 #[path = "models/db"]
422 mod foo {
423 #[path = "users.rs"]
424 mod bar;
425 }
426
427 //- /models/db/users.rs
428 pub struct Baz;
429 "###,
430 );
431
432 assert_snapshot!(map, @r###"
433 â‹®crate
434 â‹®foo: t
435 â‹®
436 â‹®crate::foo
437 â‹®bar: t
438 â‹®
439 â‹®crate::foo::bar
440 â‹®Baz: t v
441 "###);
442}
443
444#[test]
445fn module_resolution_decl_inside_inline_module_empty_path() {
446 let map = def_map(
447 r###"
448 //- /main.rs
449 #[path = ""]
450 mod foo {
451 #[path = "users.rs"]
452 mod bar;
453 }
454
455 //- /users.rs
456 pub struct Baz;
457 "###,
458 );
459
460 assert_snapshot!(map, @r###"
461 â‹®crate
462 â‹®foo: t
463 â‹®
464 â‹®crate::foo
465 â‹®bar: t
466 â‹®
467 â‹®crate::foo::bar
468 â‹®Baz: t v
469 "###);
470}
471
472#[test]
473fn module_resolution_decl_empty_path() {
474 let map = def_map(
475 r###"
476 //- /main.rs
477 #[path = ""] // Should try to read `/` (a directory)
478 mod foo;
479
480 //- /foo.rs
481 pub struct Baz;
482 "###,
483 );
484
485 assert_snapshot!(map, @r###"
486 â‹®crate
487 "###);
488}
489
490#[test]
491fn module_resolution_decl_inside_inline_module_relative_path() {
492 let map = def_map(
493 r###"
494 //- /main.rs
495 #[path = "./models"]
496 mod foo {
497 mod bar;
498 }
499
500 //- /models/bar.rs
501 pub struct Baz;
502 "###,
503 );
504
505 assert_snapshot!(map, @r###"
506 â‹®crate
507 â‹®foo: t
508 â‹®
509 â‹®crate::foo
510 â‹®bar: t
511 â‹®
512 â‹®crate::foo::bar
513 â‹®Baz: t v
514 "###);
515}
516
517#[test]
518fn module_resolution_decl_inside_inline_module_in_crate_root() {
519 let map = def_map(
520 r###"
521 //- /main.rs
522 mod foo {
523 #[path = "baz.rs"]
524 mod bar;
525 }
526 use self::foo::bar::Baz;
527
528 //- /foo/baz.rs
529 pub struct Baz;
530 "###,
531 );
532
533 assert_snapshot!(map, @r###"
534 â‹®crate
535 â‹®Baz: t v
536 â‹®foo: t
537 â‹®
538 â‹®crate::foo
539 â‹®bar: t
540 â‹®
541 â‹®crate::foo::bar
542 â‹®Baz: t v
543 "###);
544}
545
546#[test]
547fn module_resolution_decl_inside_inline_module_in_mod_rs() {
548 let map = def_map(
549 r###"
550 //- /main.rs
551 mod foo;
552
553 //- /foo/mod.rs
554 mod bar {
555 #[path = "qwe.rs"]
556 pub mod baz;
557 }
558 use self::bar::baz::Baz;
559
560 //- /foo/bar/qwe.rs
561 pub struct Baz;
562 "###,
563 );
564
565 assert_snapshot!(map, @r###"
566 â‹®crate
567 â‹®foo: t
568 â‹®
569 â‹®crate::foo
570 â‹®Baz: t v
571 â‹®bar: t
572 â‹®
573 â‹®crate::foo::bar
574 â‹®baz: t
575 â‹®
576 â‹®crate::foo::bar::baz
577 â‹®Baz: t v
578 "###);
579}
580
581#[test]
582fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
583 let map = def_map(
584 r###"
585 //- /main.rs
586 mod foo;
587
588 //- /foo.rs
589 mod bar {
590 #[path = "qwe.rs"]
591 pub mod baz;
592 }
593 use self::bar::baz::Baz;
594
595 //- /foo/bar/qwe.rs
596 pub struct Baz;
597 "###,
598 );
599
600 assert_snapshot!(map, @r###"
601 â‹®crate
602 â‹®foo: t
603 â‹®
604 â‹®crate::foo
605 â‹®Baz: t v
606 â‹®bar: t
607 â‹®
608 â‹®crate::foo::bar
609 â‹®baz: t
610 â‹®
611 â‹®crate::foo::bar::baz
612 â‹®Baz: t v
613 "###);
614}
615
616#[test]
617fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
618 let map = def_map(
619 r###"
620 //- /main.rs
621 mod foo;
622
623 //- /foo.rs
624 #[path = "bar"]
625 mod bar {
626 pub mod baz;
627 }
628 use self::bar::baz::Baz;
629
630 //- /bar/baz.rs
631 pub struct Baz;
632 "###,
633 );
634
635 assert_snapshot!(map, @r###"
636 â‹®crate
637 â‹®foo: t
638 â‹®
639 â‹®crate::foo
640 â‹®Baz: t v
641 â‹®bar: t
642 â‹®
643 â‹®crate::foo::bar
644 â‹®baz: t
645 â‹®
646 â‹®crate::foo::bar::baz
647 â‹®Baz: t v
648 "###);
649}
650
651#[test]
652fn unresolved_module_diagnostics() {
653 let diagnostics = MockDatabase::with_files(
654 r"
655 //- /lib.rs
656 mod foo;
657 mod bar;
658 mod baz {}
659 //- /foo.rs
660 ",
661 )
662 .diagnostics();
663
664 assert_snapshot!(diagnostics, @r###"
665 "mod bar;": unresolved module
666 "###
667 );
668}
669
670#[test]
671fn module_resolution_decl_inside_module_in_non_crate_root_2() {
672 let map = def_map(
673 r###"
674 //- /main.rs
675 #[path="module/m2.rs"]
676 mod module;
677
678 //- /module/m2.rs
679 pub mod submod;
680
681 //- /module/submod.rs
682 pub struct Baz;
683 "###,
684 );
685
686 assert_snapshot!(map, @r###"
687 â‹®crate
688 â‹®module: t
689 â‹®
690 â‹®crate::module
691 â‹®submod: t
692 â‹®
693 â‹®crate::module::submod
694 â‹®Baz: t v
695 "###);
696}
697
698#[test]
699fn nested_out_of_line_module() {
700 let map = def_map(
701 r###"
702 //- /lib.rs
703 mod a {
704 mod b {
705 mod c;
706 }
707 }
708
709 //- /a/b/c.rs
710 struct X;
711 "###,
712 );
713
714 assert_snapshot!(map, @r###"
715 crate
716 a: t
717
718 crate::a
719 b: t
720
721 crate::a::b
722 c: t
723
724 crate::a::b::c
725 X: t v
726 "###);
727}
728
729#[test]
730fn nested_out_of_line_module_with_path() {
731 let map = def_map(
732 r###"
733 //- /lib.rs
734 mod a {
735 #[path = "d/e"]
736 mod b {
737 mod c;
738 }
739 }
740
741 //- /a/d/e/c.rs
742 struct X;
743 "###,
744 );
745
746 assert_snapshot!(map, @r###"
747 crate
748 a: t
749
750 crate::a
751 b: t
752
753 crate::a::b
754 c: t
755
756 crate::a::b::c
757 X: t v
758 "###);
759}
diff --git a/crates/ra_hir/src/nameres/tests/primitives.rs b/crates/ra_hir/src/nameres/tests/primitives.rs
deleted file mode 100644
index 0e2708658..000000000
--- a/crates/ra_hir/src/nameres/tests/primitives.rs
+++ /dev/null
@@ -1,24 +0,0 @@
1use super::*;
2
3#[test]
4fn primitive_reexport() {
5 let map = def_map(
6 "
7 //- /lib.rs
8 mod foo;
9 use foo::int;
10
11 //- /foo.rs
12 pub use i32 as int;
13 ",
14 );
15 assert_snapshot!(map, @r###"
16 â‹®crate
17 â‹®foo: t
18 â‹®int: t
19 â‹®
20 â‹®crate::foo
21 â‹®int: t
22 "###
23 );
24}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index f77c9df9f..b932b0c8c 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -2,8 +2,10 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_def::{ 4use hir_def::{
5 builtin_type::BuiltinType,
6 nameres::CrateDefMap,
5 path::{Path, PathKind}, 7 path::{Path, PathKind},
6 CrateModuleId, 8 AdtId, CrateModuleId, ModuleDefId,
7}; 9};
8use hir_expand::name::{self, Name}; 10use hir_expand::name::{self, Name};
9use rustc_hash::FxHashSet; 11use rustc_hash::FxHashSet;
@@ -17,9 +19,8 @@ use crate::{
17 }, 19 },
18 generics::GenericParams, 20 generics::GenericParams,
19 impl_block::ImplBlock, 21 impl_block::ImplBlock,
20 nameres::{CrateDefMap, PerNs}, 22 Adt, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, PerNs, Static, Struct, Trait,
21 Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct, 23 TypeAlias,
22 Trait, TypeAlias,
23}; 24};
24 25
25#[derive(Debug, Clone, Default)] 26#[derive(Debug, Clone, Default)]
@@ -90,7 +91,7 @@ impl Resolver {
90 pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option<Trait> { 91 pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option<Trait> {
91 let res = self.resolve_module_path(db, path).take_types()?; 92 let res = self.resolve_module_path(db, path).take_types()?;
92 match res { 93 match res {
93 ModuleDef::Trait(it) => Some(it), 94 ModuleDefId::TraitId(it) => Some(it.into()),
94 _ => None, 95 _ => None,
95 } 96 }
96 } 97 }
@@ -103,7 +104,7 @@ impl Resolver {
103 ) -> Option<Struct> { 104 ) -> Option<Struct> {
104 let res = self.resolve_module_path(db, path).take_types()?; 105 let res = self.resolve_module_path(db, path).take_types()?;
105 match res { 106 match res {
106 ModuleDef::Adt(Adt::Struct(it)) => Some(it), 107 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it.into()),
107 _ => None, 108 _ => None,
108 } 109 }
109 } 110 }
@@ -112,7 +113,7 @@ impl Resolver {
112 pub(crate) fn resolve_known_enum(&self, db: &impl HirDatabase, path: &Path) -> Option<Enum> { 113 pub(crate) fn resolve_known_enum(&self, db: &impl HirDatabase, path: &Path) -> Option<Enum> {
113 let res = self.resolve_module_path(db, path).take_types()?; 114 let res = self.resolve_module_path(db, path).take_types()?;
114 match res { 115 match res {
115 ModuleDef::Adt(Adt::Enum(it)) => Some(it), 116 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it.into()),
116 _ => None, 117 _ => None,
117 } 118 }
118 } 119 }
@@ -166,18 +167,18 @@ impl Resolver {
166 Scope::ModuleScope(m) => { 167 Scope::ModuleScope(m) => {
167 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); 168 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
168 let res = match module_def.take_types()? { 169 let res = match module_def.take_types()? {
169 ModuleDef::Adt(it) => TypeNs::Adt(it), 170 ModuleDefId::AdtId(it) => TypeNs::Adt(it.into()),
170 ModuleDef::EnumVariant(it) => TypeNs::EnumVariant(it), 171 ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariant(it.into()),
171 172
172 ModuleDef::TypeAlias(it) => TypeNs::TypeAlias(it), 173 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAlias(it.into()),
173 ModuleDef::BuiltinType(it) => TypeNs::BuiltinType(it), 174 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
174 175
175 ModuleDef::Trait(it) => TypeNs::Trait(it), 176 ModuleDefId::TraitId(it) => TypeNs::Trait(it.into()),
176 177
177 ModuleDef::Function(_) 178 ModuleDefId::FunctionId(_)
178 | ModuleDef::Const(_) 179 | ModuleDefId::ConstId(_)
179 | ModuleDef::Static(_) 180 | ModuleDefId::StaticId(_)
180 | ModuleDef::Module(_) => return None, 181 | ModuleDefId::ModuleId(_) => return None,
181 }; 182 };
182 return Some((res, idx)); 183 return Some((res, idx));
183 } 184 }
@@ -261,33 +262,35 @@ impl Resolver {
261 return match idx { 262 return match idx {
262 None => { 263 None => {
263 let value = match module_def.take_values()? { 264 let value = match module_def.take_values()? {
264 ModuleDef::Function(it) => ValueNs::Function(it), 265 ModuleDefId::FunctionId(it) => ValueNs::Function(it.into()),
265 ModuleDef::Adt(Adt::Struct(it)) => ValueNs::Struct(it), 266 ModuleDefId::AdtId(AdtId::StructId(it)) => {
266 ModuleDef::EnumVariant(it) => ValueNs::EnumVariant(it), 267 ValueNs::Struct(it.into())
267 ModuleDef::Const(it) => ValueNs::Const(it), 268 }
268 ModuleDef::Static(it) => ValueNs::Static(it), 269 ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariant(it.into()),
269 270 ModuleDefId::ConstId(it) => ValueNs::Const(it.into()),
270 ModuleDef::Adt(Adt::Enum(_)) 271 ModuleDefId::StaticId(it) => ValueNs::Static(it.into()),
271 | ModuleDef::Adt(Adt::Union(_)) 272
272 | ModuleDef::Trait(_) 273 ModuleDefId::AdtId(AdtId::EnumId(_))
273 | ModuleDef::TypeAlias(_) 274 | ModuleDefId::AdtId(AdtId::UnionId(_))
274 | ModuleDef::BuiltinType(_) 275 | ModuleDefId::TraitId(_)
275 | ModuleDef::Module(_) => return None, 276 | ModuleDefId::TypeAliasId(_)
277 | ModuleDefId::BuiltinType(_)
278 | ModuleDefId::ModuleId(_) => return None,
276 }; 279 };
277 Some(ResolveValueResult::ValueNs(value)) 280 Some(ResolveValueResult::ValueNs(value))
278 } 281 }
279 Some(idx) => { 282 Some(idx) => {
280 let ty = match module_def.take_types()? { 283 let ty = match module_def.take_types()? {
281 ModuleDef::Adt(it) => TypeNs::Adt(it), 284 ModuleDefId::AdtId(it) => TypeNs::Adt(it.into()),
282 ModuleDef::Trait(it) => TypeNs::Trait(it), 285 ModuleDefId::TraitId(it) => TypeNs::Trait(it.into()),
283 ModuleDef::TypeAlias(it) => TypeNs::TypeAlias(it), 286 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAlias(it.into()),
284 ModuleDef::BuiltinType(it) => TypeNs::BuiltinType(it), 287 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
285 288
286 ModuleDef::Module(_) 289 ModuleDefId::ModuleId(_)
287 | ModuleDef::Function(_) 290 | ModuleDefId::FunctionId(_)
288 | ModuleDef::EnumVariant(_) 291 | ModuleDefId::EnumVariantId(_)
289 | ModuleDef::Const(_) 292 | ModuleDefId::ConstId(_)
290 | ModuleDef::Static(_) => return None, 293 | ModuleDefId::StaticId(_) => return None,
291 }; 294 };
292 Some(ResolveValueResult::Partial(ty, idx)) 295 Some(ResolveValueResult::Partial(ty, idx))
293 } 296 }
@@ -315,7 +318,7 @@ impl Resolver {
315 path: &Path, 318 path: &Path,
316 ) -> Option<MacroDef> { 319 ) -> Option<MacroDef> {
317 let (item_map, module) = self.module()?; 320 let (item_map, module) = self.module()?;
318 item_map.resolve_path(db, module, path).0.get_macros() 321 item_map.resolve_path(db, module, path).0.get_macros().map(MacroDef::from)
319 } 322 }
320 323
321 pub(crate) fn process_all_names( 324 pub(crate) fn process_all_names(
@@ -333,10 +336,11 @@ impl Resolver {
333 for scope in &self.scopes { 336 for scope in &self.scopes {
334 if let Scope::ModuleScope(m) = scope { 337 if let Scope::ModuleScope(m) = scope {
335 if let Some(prelude) = m.crate_def_map.prelude() { 338 if let Some(prelude) = m.crate_def_map.prelude() {
336 let prelude_def_map = db.crate_def_map(prelude.krate()); 339 let prelude_def_map = db.crate_def_map(prelude.krate);
337 traits.extend(prelude_def_map[prelude.id.module_id].scope.traits()); 340 traits
341 .extend(prelude_def_map[prelude.module_id].scope.traits().map(Trait::from));
338 } 342 }
339 traits.extend(m.crate_def_map[m.module_id].scope.traits()); 343 traits.extend(m.crate_def_map[m.module_id].scope.traits().map(Trait::from));
340 } 344 }
341 } 345 }
342 traits 346 traits
@@ -351,7 +355,7 @@ impl Resolver {
351 } 355 }
352 356
353 pub(crate) fn krate(&self) -> Option<Crate> { 357 pub(crate) fn krate(&self) -> Option<Crate> {
354 self.module().map(|t| t.0.krate()) 358 self.module().map(|t| Crate { crate_id: t.0.krate() })
355 } 359 }
356 360
357 pub(crate) fn where_predicates_in_scope<'a>( 361 pub(crate) fn where_predicates_in_scope<'a>(
@@ -420,8 +424,10 @@ impl From<PerNs> for ScopeDef {
420 fn from(def: PerNs) -> Self { 424 fn from(def: PerNs) -> Self {
421 def.take_types() 425 def.take_types()
422 .or_else(|| def.take_values()) 426 .or_else(|| def.take_values())
423 .map(ScopeDef::ModuleDef) 427 .map(|module_def_id| ScopeDef::ModuleDef(module_def_id.into()))
424 .or_else(|| def.get_macros().map(ScopeDef::MacroDef)) 428 .or_else(|| {
429 def.get_macros().map(|macro_def_id| ScopeDef::MacroDef(macro_def_id.into()))
430 })
425 .unwrap_or(ScopeDef::Unknown) 431 .unwrap_or(ScopeDef::Unknown)
426 } 432 }
427} 433}
@@ -441,18 +447,16 @@ impl Scope {
441 f(name.clone(), res.def.into()); 447 f(name.clone(), res.def.into());
442 }); 448 });
443 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { 449 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
444 f(name.clone(), ScopeDef::MacroDef(macro_)); 450 f(name.clone(), ScopeDef::MacroDef(macro_.into()));
445 }); 451 });
446 m.crate_def_map.extern_prelude().iter().for_each(|(name, def)| { 452 m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| {
447 f(name.clone(), ScopeDef::ModuleDef(*def)); 453 f(name.clone(), ScopeDef::ModuleDef(def.into()));
448 }); 454 });
449 if let Some(prelude) = m.crate_def_map.prelude() { 455 if let Some(prelude) = m.crate_def_map.prelude() {
450 let prelude_def_map = db.crate_def_map(prelude.krate()); 456 let prelude_def_map = db.crate_def_map(prelude.krate);
451 prelude_def_map[prelude.id.module_id].scope.entries().for_each( 457 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| {
452 |(name, res)| { 458 f(name.clone(), res.def.into());
453 f(name.clone(), res.def.into()); 459 });
454 },
455 );
456 } 460 }
457 } 461 }
458 Scope::GenericParams(gp) => { 462 Scope::GenericParams(gp) => {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 01f51ba5d..66cb4b357 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -12,7 +12,7 @@ use hir_expand::name::AsName;
12use ra_db::FileId; 12use ra_db::FileId;
13use ra_syntax::{ 13use ra_syntax::{
14 ast::{self, AstNode}, 14 ast::{self, AstNode},
15 AstPtr, 15 match_ast, AstPtr,
16 SyntaxKind::*, 16 SyntaxKind::*,
17 SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, 17 SyntaxNode, SyntaxNodePtr, TextRange, TextUnit,
18}; 18};
@@ -27,9 +27,9 @@ use crate::{
27 }, 27 },
28 ids::LocationCtx, 28 ids::LocationCtx,
29 resolve::{ScopeDef, TypeNs, ValueNs}, 29 resolve::{ScopeDef, TypeNs, ValueNs},
30 ty::method_resolution::implements_trait, 30 ty::method_resolution::{self, implements_trait},
31 Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, Module, 31 AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId,
32 Name, Path, Resolver, Static, Struct, Ty, 32 MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty,
33}; 33};
34 34
35fn try_get_resolver_for_node( 35fn try_get_resolver_for_node(
@@ -37,24 +37,34 @@ fn try_get_resolver_for_node(
37 file_id: FileId, 37 file_id: FileId,
38 node: &SyntaxNode, 38 node: &SyntaxNode,
39) -> Option<Resolver> { 39) -> Option<Resolver> {
40 if let Some(module) = ast::Module::cast(node.clone()) { 40 match_ast! {
41 let src = crate::Source { file_id: file_id.into(), ast: module }; 41 match node {
42 Some(crate::Module::from_declaration(db, src)?.resolver(db)) 42 ast::Module(it) => {
43 } else if let Some(file) = ast::SourceFile::cast(node.clone()) { 43 let src = crate::Source { file_id: file_id.into(), ast: it };
44 let src = 44 Some(crate::Module::from_declaration(db, src)?.resolver(db))
45 crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(file) }; 45 },
46 Some(crate::Module::from_definition(db, src)?.resolver(db)) 46 ast::SourceFile(it) => {
47 } else if let Some(s) = ast::StructDef::cast(node.clone()) { 47 let src =
48 let src = crate::Source { file_id: file_id.into(), ast: s }; 48 crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(it) };
49 Some(Struct::from_source(db, src)?.resolver(db)) 49 Some(crate::Module::from_definition(db, src)?.resolver(db))
50 } else if let Some(e) = ast::EnumDef::cast(node.clone()) { 50 },
51 let src = crate::Source { file_id: file_id.into(), ast: e }; 51 ast::StructDef(it) => {
52 Some(Enum::from_source(db, src)?.resolver(db)) 52 let src = crate::Source { file_id: file_id.into(), ast: it };
53 } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { 53 Some(Struct::from_source(db, src)?.resolver(db))
54 Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) 54 },
55 } else { 55 ast::EnumDef(it) => {
56 // FIXME add missing cases 56 let src = crate::Source { file_id: file_id.into(), ast: it };
57 None 57 Some(Enum::from_source(db, src)?.resolver(db))
58 },
59 _ => {
60 if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
61 Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db))
62 } else {
63 // FIXME add missing cases
64 None
65 }
66 },
67 }
58 } 68 }
59} 69}
60 70
@@ -68,16 +78,14 @@ fn def_with_body_from_child_node(
68 let ctx = LocationCtx::new(db, module.id, file_id.into()); 78 let ctx = LocationCtx::new(db, module.id, file_id.into());
69 79
70 node.ancestors().find_map(|node| { 80 node.ancestors().find_map(|node| {
71 if let Some(def) = ast::FnDef::cast(node.clone()) { 81 match_ast! {
72 return Some(Function { id: ctx.to_def(&def) }.into()); 82 match node {
73 } 83 ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) },
74 if let Some(def) = ast::ConstDef::cast(node.clone()) { 84 ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) },
75 return Some(Const { id: ctx.to_def(&def) }.into()); 85 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) },
76 } 86 _ => { None },
77 if let Some(def) = ast::StaticDef::cast(node) { 87 }
78 return Some(Static { id: ctx.to_def(&def) }.into());
79 } 88 }
80 None
81 }) 89 })
82} 90}
83 91
@@ -245,9 +253,14 @@ impl SourceAnalyzer {
245 Some(res) 253 Some(res)
246 }); 254 });
247 255
248 let items = 256 let items = self
249 self.resolver.resolve_module_path(db, &path).take_types().map(PathResolution::Def); 257 .resolver
250 types.or(values).or(items) 258 .resolve_module_path(db, &path)
259 .take_types()
260 .map(|it| PathResolution::Def(it.into()));
261 types.or(values).or(items).or_else(|| {
262 self.resolver.resolve_path_as_macro(db, &path).map(|def| PathResolution::Macro(def))
263 })
251 } 264 }
252 265
253 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { 266 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
@@ -317,16 +330,42 @@ impl SourceAnalyzer {
317 db: &impl HirDatabase, 330 db: &impl HirDatabase,
318 ty: Ty, 331 ty: Ty,
319 name: Option<&Name>, 332 name: Option<&Name>,
320 callback: impl FnMut(&Ty, Function) -> Option<T>, 333 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
334 ) -> Option<T> {
335 // There should be no inference vars in types passed here
336 // FIXME check that?
337 // FIXME replace Unknown by bound vars here
338 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
339 method_resolution::iterate_method_candidates(
340 &canonical,
341 db,
342 &self.resolver,
343 name,
344 method_resolution::LookupMode::MethodCall,
345 |ty, it| match it {
346 AssocItem::Function(f) => callback(ty, f),
347 _ => None,
348 },
349 )
350 }
351
352 pub fn iterate_path_candidates<T>(
353 &self,
354 db: &impl HirDatabase,
355 ty: Ty,
356 name: Option<&Name>,
357 callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
321 ) -> Option<T> { 358 ) -> Option<T> {
322 // There should be no inference vars in types passed here 359 // There should be no inference vars in types passed here
323 // FIXME check that? 360 // FIXME check that?
361 // FIXME replace Unknown by bound vars here
324 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 362 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
325 crate::ty::method_resolution::iterate_method_candidates( 363 method_resolution::iterate_method_candidates(
326 &canonical, 364 &canonical,
327 db, 365 db,
328 &self.resolver, 366 &self.resolver,
329 name, 367 name,
368 method_resolution::LookupMode::Path,
330 callback, 369 callback,
331 ) 370 )
332 } 371 }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index d2bfcdc7d..d1a9d7411 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -385,13 +385,22 @@ impl SubstsBuilder {
385 self.param_count - self.vec.len() 385 self.param_count - self.vec.len()
386 } 386 }
387 387
388 pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self { 388 pub fn fill_with_bound_vars(self, starting_from: u32) -> Self {
389 self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound)); 389 self.fill((starting_from..).map(Ty::Bound))
390 self 390 }
391
392 pub fn fill_with_params(self) -> Self {
393 let start = self.vec.len() as u32;
394 self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
395 }
396
397 pub fn fill_with_unknown(self) -> Self {
398 self.fill(iter::repeat(Ty::Unknown))
391 } 399 }
392 400
393 pub fn fill_with_unknown(mut self) -> Self { 401 pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
394 self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining())); 402 self.vec.extend(filler.take(self.remaining()));
403 assert_eq!(self.remaining(), 0);
395 self 404 self
396 } 405 }
397 406
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 6694467a3..2370e8d4f 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -25,7 +25,7 @@ use hir_def::{
25 path::known, 25 path::known,
26 type_ref::{Mutability, TypeRef}, 26 type_ref::{Mutability, TypeRef},
27}; 27};
28use hir_expand::name; 28use hir_expand::{diagnostics::DiagnosticSink, name};
29use ra_arena::map::ArenaMap; 29use ra_arena::map::ArenaMap;
30use ra_prof::profile; 30use ra_prof::profile;
31use test_utils::tested_by; 31use test_utils::tested_by;
@@ -40,7 +40,6 @@ use crate::{
40 adt::VariantDef, 40 adt::VariantDef,
41 code_model::TypeAlias, 41 code_model::TypeAlias,
42 db::HirDatabase, 42 db::HirDatabase,
43 diagnostics::DiagnosticSink,
44 expr::{BindingAnnotation, Body, ExprId, PatId}, 43 expr::{BindingAnnotation, Body, ExprId, PatId},
45 resolve::{Resolver, TypeNs}, 44 resolve::{Resolver, TypeNs},
46 ty::infer::diagnostics::InferenceDiagnostic, 45 ty::infer::diagnostics::InferenceDiagnostic,
@@ -719,12 +718,9 @@ impl Expectation {
719} 718}
720 719
721mod diagnostics { 720mod diagnostics {
722 use crate::{ 721 use hir_expand::diagnostics::DiagnosticSink;
723 db::HirDatabase, 722
724 diagnostics::{DiagnosticSink, NoSuchField}, 723 use crate::{db::HirDatabase, diagnostics::NoSuchField, expr::ExprId, Function, HasSource};
725 expr::ExprId,
726 Function, HasSource,
727 };
728 724
729 #[derive(Debug, PartialEq, Eq, Clone)] 725 #[derive(Debug, PartialEq, Eq, Clone)]
730 pub(super) enum InferenceDiagnostic { 726 pub(super) enum InferenceDiagnostic {
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index fed52df39..a09ef5c5d 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -11,12 +11,11 @@ use crate::{
11 db::HirDatabase, 11 db::HirDatabase,
12 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 12 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
13 generics::{GenericParams, HasGenericParams}, 13 generics::{GenericParams, HasGenericParams},
14 nameres::Namespace,
15 ty::{ 14 ty::{
16 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation, 15 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation,
17 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 16 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
18 }, 17 },
19 Adt, Name, 18 Adt, Name, Namespace,
20}; 19};
21 20
22impl<'a, D: HirDatabase> InferenceContext<'a, D> { 21impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 77aa35ce1..59b7f7eb6 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -6,8 +6,8 @@ use super::{ExprOrPatId, InferenceContext, TraitRef};
6use crate::{ 6use crate::{
7 db::HirDatabase, 7 db::HirDatabase,
8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 8 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
9 ty::{Substs, Ty, TypableDef, TypeWalk}, 9 ty::{method_resolution, Substs, Ty, TypableDef, TypeWalk},
10 AssocItem, HasGenericParams, Namespace, Path, 10 AssocItem, Container, HasGenericParams, Name, Namespace, Path,
11}; 11};
12 12
13impl<'a, D: HirDatabase> InferenceContext<'a, D> { 13impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -39,7 +39,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
39 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); 39 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
40 self.resolve_ty_assoc_item( 40 self.resolve_ty_assoc_item(
41 ty, 41 ty,
42 path.segments.last().expect("path had at least one segment"), 42 &path.segments.last().expect("path had at least one segment").name,
43 id, 43 id,
44 )? 44 )?
45 } else { 45 } else {
@@ -122,10 +122,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
122 return None; 122 return None;
123 } 123 }
124 124
125 let ty = self.insert_type_vars(ty);
126 let ty = self.normalize_associated_types_in(ty);
127
125 let segment = 128 let segment =
126 remaining_segments.last().expect("there should be at least one segment here"); 129 remaining_segments.last().expect("there should be at least one segment here");
127 130
128 self.resolve_ty_assoc_item(ty, segment, id) 131 self.resolve_ty_assoc_item(ty, &segment.name, id)
129 } 132 }
130 } 133 }
131 } 134 }
@@ -162,7 +165,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
162 }; 165 };
163 let substs = Substs::build_for_def(self.db, item) 166 let substs = Substs::build_for_def(self.db, item)
164 .use_parent_substs(&trait_ref.substs) 167 .use_parent_substs(&trait_ref.substs)
165 .fill_with_unknown() 168 .fill_with_params()
166 .build(); 169 .build();
167 170
168 self.write_assoc_resolution(id, item); 171 self.write_assoc_resolution(id, item);
@@ -172,44 +175,51 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
172 fn resolve_ty_assoc_item( 175 fn resolve_ty_assoc_item(
173 &mut self, 176 &mut self,
174 ty: Ty, 177 ty: Ty,
175 segment: &PathSegment, 178 name: &Name,
176 id: ExprOrPatId, 179 id: ExprOrPatId,
177 ) -> Option<(ValueNs, Option<Substs>)> { 180 ) -> Option<(ValueNs, Option<Substs>)> {
178 if let Ty::Unknown = ty { 181 if let Ty::Unknown = ty {
179 return None; 182 return None;
180 } 183 }
181 184
182 let krate = self.resolver.krate()?; 185 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
183 186
184 // Find impl 187 method_resolution::iterate_method_candidates(
185 // FIXME: consider trait candidates 188 &canonical_ty.value,
186 let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item { 189 self.db,
187 AssocItem::Function(func) => { 190 &self.resolver.clone(),
188 if segment.name == func.name(self.db) { 191 Some(name),
189 Some(AssocItem::Function(func)) 192 method_resolution::LookupMode::Path,
190 } else { 193 move |_ty, item| {
191 None 194 let def = match item {
192 } 195 AssocItem::Function(f) => ValueNs::Function(f),
193 } 196 AssocItem::Const(c) => ValueNs::Const(c),
194 197 AssocItem::TypeAlias(_) => unreachable!(),
195 AssocItem::Const(konst) => { 198 };
196 if konst.name(self.db).map_or(false, |n| n == segment.name) { 199 let substs = match item.container(self.db) {
197 Some(AssocItem::Const(konst)) 200 Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()),
198 } else { 201 Container::Trait(t) => {
199 None 202 // we're picking this method
200 } 203 let trait_substs = Substs::build_for_def(self.db, t)
201 } 204 .push(ty.clone())
202 AssocItem::TypeAlias(_) => None, 205 .fill(std::iter::repeat_with(|| self.new_type_var()))
203 })?; 206 .build();
204 let def = match item { 207 let substs = Substs::build_for_def(self.db, item)
205 AssocItem::Function(f) => ValueNs::Function(f), 208 .use_parent_substs(&trait_substs)
206 AssocItem::Const(c) => ValueNs::Const(c), 209 .fill_with_params()
207 AssocItem::TypeAlias(_) => unreachable!(), 210 .build();
208 }; 211 self.obligations.push(super::Obligation::Trait(TraitRef {
209 let substs = self.find_self_types(&def, ty); 212 trait_: t,
213 substs: trait_substs,
214 }));
215 Some(substs)
216 }
217 };
210 218
211 self.write_assoc_resolution(id, item); 219 self.write_assoc_resolution(id, item);
212 Some((def, substs)) 220 Some((def, substs))
221 },
222 )
213 } 223 }
214 224
215 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { 225 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 0f49a0e54..e29ab8492 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -9,6 +9,7 @@ use std::iter;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use hir_def::{ 11use hir_def::{
12 builtin_type::BuiltinType,
12 path::{GenericArg, PathSegment}, 13 path::{GenericArg, PathSegment},
13 type_ref::{TypeBound, TypeRef}, 14 type_ref::{TypeBound, TypeRef},
14}; 15};
@@ -22,11 +23,13 @@ use crate::{
22 db::HirDatabase, 23 db::HirDatabase,
23 generics::HasGenericParams, 24 generics::HasGenericParams,
24 generics::{GenericDef, WherePredicate}, 25 generics::{GenericDef, WherePredicate},
25 nameres::Namespace,
26 resolve::{Resolver, TypeNs}, 26 resolve::{Resolver, TypeNs},
27 ty::Adt, 27 ty::{
28 primitive::{FloatTy, IntTy},
29 Adt,
30 },
28 util::make_mut_slice, 31 util::make_mut_slice,
29 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, 32 Const, Enum, EnumVariant, Function, ModuleDef, Namespace, Path, Static, Struct, StructField,
30 Trait, TypeAlias, Union, 33 Trait, TypeAlias, Union,
31}; 34};
32 35
@@ -643,14 +646,16 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
643 BuiltinType::Char => TypeCtor::Char, 646 BuiltinType::Char => TypeCtor::Char,
644 BuiltinType::Bool => TypeCtor::Bool, 647 BuiltinType::Bool => TypeCtor::Bool,
645 BuiltinType::Str => TypeCtor::Str, 648 BuiltinType::Str => TypeCtor::Str,
646 BuiltinType::Int(ty) => TypeCtor::Int(ty.into()), 649 BuiltinType::Int { signedness, bitness } => {
647 BuiltinType::Float(ty) => TypeCtor::Float(ty.into()), 650 TypeCtor::Int(IntTy { signedness, bitness }.into())
651 }
652 BuiltinType::Float { bitness } => TypeCtor::Float(FloatTy { bitness }.into()),
648 }) 653 })
649} 654}
650 655
651fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { 656fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
652 let var_data = def.variant_data(db); 657 let struct_data = db.struct_data(def.id);
653 let fields = match var_data.fields() { 658 let fields = match struct_data.variant_data.fields() {
654 Some(fields) => fields, 659 Some(fields) => fields,
655 None => panic!("fn_sig_for_struct_constructor called on unit struct"), 660 None => panic!("fn_sig_for_struct_constructor called on unit struct"),
656 }; 661 };
@@ -665,8 +670,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
665 670
666/// Build the type of a tuple struct constructor. 671/// Build the type of a tuple struct constructor.
667fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 672fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
668 let var_data = def.variant_data(db); 673 let struct_data = db.struct_data(def.id);
669 if var_data.fields().is_none() { 674 if struct_data.variant_data.fields().is_none() {
670 return type_for_adt(db, def); // Unit struct 675 return type_for_adt(db, def); // Unit struct
671 } 676 }
672 let generics = def.generic_params(db); 677 let generics = def.generic_params(db);
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index eb69344f6..8c3d32d09 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -166,37 +166,78 @@ pub(crate) fn lookup_method(
166 name: &Name, 166 name: &Name,
167 resolver: &Resolver, 167 resolver: &Resolver,
168) -> Option<(Ty, Function)> { 168) -> Option<(Ty, Function)> {
169 iterate_method_candidates(ty, db, resolver, Some(name), |ty, f| Some((ty.clone(), f))) 169 iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f
170 {
171 AssocItem::Function(f) => Some((ty.clone(), f)),
172 _ => None,
173 })
174}
175
176/// Whether we're looking up a dotted method call (like `v.len()`) or a path
177/// (like `Vec::new`).
178#[derive(Copy, Clone, Debug, PartialEq, Eq)]
179pub enum LookupMode {
180 /// Looking up a method call like `v.len()`: We only consider candidates
181 /// that have a `self` parameter, and do autoderef.
182 MethodCall,
183 /// Looking up a path like `Vec::new` or `Vec::default`: We consider all
184 /// candidates including associated constants, but don't do autoderef.
185 Path,
170} 186}
171 187
172// This would be nicer if it just returned an iterator, but that runs into 188// This would be nicer if it just returned an iterator, but that runs into
173// lifetime problems, because we need to borrow temp `CrateImplBlocks`. 189// lifetime problems, because we need to borrow temp `CrateImplBlocks`.
190// FIXME add a context type here?
174pub(crate) fn iterate_method_candidates<T>( 191pub(crate) fn iterate_method_candidates<T>(
175 ty: &Canonical<Ty>, 192 ty: &Canonical<Ty>,
176 db: &impl HirDatabase, 193 db: &impl HirDatabase,
177 resolver: &Resolver, 194 resolver: &Resolver,
178 name: Option<&Name>, 195 name: Option<&Name>,
179 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 196 mode: LookupMode,
197 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
180) -> Option<T> { 198) -> Option<T> {
181 // For method calls, rust first does any number of autoderef, and then one 199 let krate = resolver.krate()?;
182 // autoref (i.e. when the method takes &self or &mut self). We just ignore 200 match mode {
183 // the autoref currently -- when we find a method matching the given name, 201 LookupMode::MethodCall => {
184 // we assume it fits. 202 // For method calls, rust first does any number of autoderef, and then one
203 // autoref (i.e. when the method takes &self or &mut self). We just ignore
204 // the autoref currently -- when we find a method matching the given name,
205 // we assume it fits.
185 206
186 // Also note that when we've got a receiver like &S, even if the method we 207 // Also note that when we've got a receiver like &S, even if the method we
187 // find in the end takes &self, we still do the autoderef step (just as 208 // find in the end takes &self, we still do the autoderef step (just as
188 // rustc does an autoderef and then autoref again). 209 // rustc does an autoderef and then autoref again).
189 210
190 let krate = resolver.krate()?; 211 for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
191 for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { 212 if let Some(result) =
192 if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback) 213 iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
193 { 214 {
194 return Some(result); 215 return Some(result);
216 }
217 if let Some(result) = iterate_trait_method_candidates(
218 &derefed_ty,
219 db,
220 resolver,
221 name,
222 mode,
223 &mut callback,
224 ) {
225 return Some(result);
226 }
227 }
195 } 228 }
196 if let Some(result) = 229 LookupMode::Path => {
197 iterate_trait_method_candidates(&derefed_ty, db, resolver, name, &mut callback) 230 // No autoderef for path lookups
198 { 231 if let Some(result) =
199 return Some(result); 232 iterate_inherent_methods(&ty, db, name, mode, krate, &mut callback)
233 {
234 return Some(result);
235 }
236 if let Some(result) =
237 iterate_trait_method_candidates(&ty, db, resolver, name, mode, &mut callback)
238 {
239 return Some(result);
240 }
200 } 241 }
201 } 242 }
202 None 243 None
@@ -207,7 +248,8 @@ fn iterate_trait_method_candidates<T>(
207 db: &impl HirDatabase, 248 db: &impl HirDatabase,
208 resolver: &Resolver, 249 resolver: &Resolver,
209 name: Option<&Name>, 250 name: Option<&Name>,
210 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 251 mode: LookupMode,
252 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
211) -> Option<T> { 253) -> Option<T> {
212 let krate = resolver.krate()?; 254 let krate = resolver.krate()?;
213 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) 255 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
@@ -231,22 +273,20 @@ fn iterate_trait_method_candidates<T>(
231 // trait, but if we find out it doesn't, we'll skip the rest of the 273 // trait, but if we find out it doesn't, we'll skip the rest of the
232 // iteration 274 // iteration
233 let mut known_implemented = inherently_implemented; 275 let mut known_implemented = inherently_implemented;
234 for item in data.items() { 276 for &item in data.items() {
235 if let AssocItem::Function(m) = *item { 277 if !is_valid_candidate(db, name, mode, item) {
236 let data = m.data(db); 278 continue;
237 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 279 }
238 if !known_implemented { 280 if !known_implemented {
239 let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); 281 let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
240 if db.trait_solve(krate, goal).is_none() { 282 if db.trait_solve(krate, goal).is_none() {
241 continue 'traits; 283 continue 'traits;
242 }
243 }
244 known_implemented = true;
245 if let Some(result) = callback(&ty.value, m) {
246 return Some(result);
247 }
248 } 284 }
249 } 285 }
286 known_implemented = true;
287 if let Some(result) = callback(&ty.value, item) {
288 return Some(result);
289 }
250 } 290 }
251 } 291 }
252 None 292 None
@@ -256,21 +296,20 @@ fn iterate_inherent_methods<T>(
256 ty: &Canonical<Ty>, 296 ty: &Canonical<Ty>,
257 db: &impl HirDatabase, 297 db: &impl HirDatabase,
258 name: Option<&Name>, 298 name: Option<&Name>,
299 mode: LookupMode,
259 krate: Crate, 300 krate: Crate,
260 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 301 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
261) -> Option<T> { 302) -> Option<T> {
262 for krate in def_crates(db, krate, &ty.value)? { 303 for krate in def_crates(db, krate, &ty.value)? {
263 let impls = db.impls_in_crate(krate); 304 let impls = db.impls_in_crate(krate);
264 305
265 for impl_block in impls.lookup_impl_blocks(&ty.value) { 306 for impl_block in impls.lookup_impl_blocks(&ty.value) {
266 for item in impl_block.items(db) { 307 for item in impl_block.items(db) {
267 if let AssocItem::Function(f) = item { 308 if !is_valid_candidate(db, name, mode, item) {
268 let data = f.data(db); 309 continue;
269 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 310 }
270 if let Some(result) = callback(&ty.value, f) { 311 if let Some(result) = callback(&ty.value, item) {
271 return Some(result); 312 return Some(result);
272 }
273 }
274 } 313 }
275 } 314 }
276 } 315 }
@@ -278,6 +317,26 @@ fn iterate_inherent_methods<T>(
278 None 317 None
279} 318}
280 319
320fn is_valid_candidate(
321 db: &impl HirDatabase,
322 name: Option<&Name>,
323 mode: LookupMode,
324 item: AssocItem,
325) -> bool {
326 match item {
327 AssocItem::Function(m) => {
328 let data = m.data(db);
329 name.map_or(true, |name| data.name() == name)
330 && (data.has_self_param() || mode == LookupMode::Path)
331 }
332 AssocItem::Const(c) => {
333 name.map_or(true, |name| Some(name) == c.name(db).as_ref())
334 && (mode == LookupMode::Path)
335 }
336 _ => false,
337 }
338}
339
281pub(crate) fn implements_trait( 340pub(crate) fn implements_trait(
282 ty: &Canonical<Ty>, 341 ty: &Canonical<Ty>,
283 db: &impl HirDatabase, 342 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 8966f9d1d..1749752f1 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -2,27 +2,7 @@
2 2
3use std::fmt; 3use std::fmt;
4 4
5#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 5pub use hir_def::builtin_type::{FloatBitness, IntBitness, Signedness};
6pub enum Signedness {
7 Signed,
8 Unsigned,
9}
10
11#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
12pub enum IntBitness {
13 Xsize,
14 X8,
15 X16,
16 X32,
17 X64,
18 X128,
19}
20
21#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
22pub enum FloatBitness {
23 X32,
24 X64,
25}
26 6
27#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 7#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
28pub enum UncertainIntTy { 8pub enum UncertainIntTy {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index c12326643..f27155737 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1841,8 +1841,8 @@ fn test() {
1841 [243; 254) 'Struct::FOO': u32 1841 [243; 254) 'Struct::FOO': u32
1842 [264; 265) 'y': u32 1842 [264; 265) 'y': u32
1843 [268; 277) 'Enum::BAR': u32 1843 [268; 277) 'Enum::BAR': u32
1844 [287; 288) 'z': {unknown} 1844 [287; 288) 'z': u32
1845 [291; 304) 'TraitTest::ID': {unknown} 1845 [291; 304) 'TraitTest::ID': u32
1846 "### 1846 "###
1847 ); 1847 );
1848} 1848}
@@ -2782,9 +2782,9 @@ fn test() {
2782 [97; 99) 's1': S 2782 [97; 99) 's1': S
2783 [105; 121) 'Defaul...efault': fn default<S>() -> Self 2783 [105; 121) 'Defaul...efault': fn default<S>() -> Self
2784 [105; 123) 'Defaul...ault()': S 2784 [105; 123) 'Defaul...ault()': S
2785 [133; 135) 's2': {unknown} 2785 [133; 135) 's2': S
2786 [138; 148) 'S::default': {unknown} 2786 [138; 148) 'S::default': fn default<S>() -> Self
2787 [138; 150) 'S::default()': {unknown} 2787 [138; 150) 'S::default()': S
2788 [160; 162) 's3': S 2788 [160; 162) 's3': S
2789 [165; 188) '<S as ...efault': fn default<S>() -> Self 2789 [165; 188) '<S as ...efault': fn default<S>() -> Self
2790 [165; 190) '<S as ...ault()': S 2790 [165; 190) '<S as ...ault()': S
@@ -2793,6 +2793,153 @@ fn test() {
2793} 2793}
2794 2794
2795#[test] 2795#[test]
2796fn infer_trait_assoc_method_generics_1() {
2797 assert_snapshot!(
2798 infer(r#"
2799trait Trait<T> {
2800 fn make() -> T;
2801}
2802struct S;
2803impl Trait<u32> for S {}
2804struct G<T>;
2805impl<T> Trait<T> for G<T> {}
2806fn test() {
2807 let a = S::make();
2808 let b = G::<u64>::make();
2809 let c: f64 = G::make();
2810}
2811"#),
2812 @r###"
2813 [127; 211) '{ ...e(); }': ()
2814 [137; 138) 'a': u32
2815 [141; 148) 'S::make': fn make<S, u32>() -> T
2816 [141; 150) 'S::make()': u32
2817 [160; 161) 'b': u64
2818 [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T
2819 [164; 180) 'G::<u6...make()': u64
2820 [190; 191) 'c': f64
2821 [199; 206) 'G::make': fn make<G<f64>, f64>() -> T
2822 [199; 208) 'G::make()': f64
2823 "###
2824 );
2825}
2826
2827#[test]
2828fn infer_trait_assoc_method_generics_2() {
2829 assert_snapshot!(
2830 infer(r#"
2831trait Trait<T> {
2832 fn make<U>() -> (T, U);
2833}
2834struct S;
2835impl Trait<u32> for S {}
2836struct G<T>;
2837impl<T> Trait<T> for G<T> {}
2838fn test() {
2839 let a = S::make::<i64>();
2840 let b: (_, i64) = S::make();
2841 let c = G::<u32>::make::<i64>();
2842 let d: (u32, _) = G::make::<i64>();
2843 let e: (u32, i64) = G::make();
2844}
2845"#),
2846 @r###"
2847 [135; 313) '{ ...e(); }': ()
2848 [145; 146) 'a': (u32, i64)
2849 [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U)
2850 [149; 165) 'S::mak...i64>()': (u32, i64)
2851 [175; 176) 'b': (u32, i64)
2852 [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U)
2853 [189; 198) 'S::make()': (u32, i64)
2854 [208; 209) 'c': (u32, i64)
2855 [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2856 [212; 235) 'G::<u3...i64>()': (u32, i64)
2857 [245; 246) 'd': (u32, i64)
2858 [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
2859 [259; 275) 'G::mak...i64>()': (u32, i64)
2860 [285; 286) 'e': (u32, i64)
2861 [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U)
2862 [301; 310) 'G::make()': (u32, i64)
2863 "###
2864 );
2865}
2866
2867#[test]
2868fn infer_trait_assoc_method_generics_3() {
2869 assert_snapshot!(
2870 infer(r#"
2871trait Trait<T> {
2872 fn make() -> (Self, T);
2873}
2874struct S<T>;
2875impl Trait<i64> for S<i32> {}
2876fn test() {
2877 let a = S::make();
2878}
2879"#),
2880 @r###"
2881 [101; 127) '{ ...e(); }': ()
2882 [111; 112) 'a': (S<i32>, i64)
2883 [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T)
2884 [115; 124) 'S::make()': (S<i32>, i64)
2885 "###
2886 );
2887}
2888
2889#[test]
2890fn infer_trait_assoc_method_generics_4() {
2891 assert_snapshot!(
2892 infer(r#"
2893trait Trait<T> {
2894 fn make() -> (Self, T);
2895}
2896struct S<T>;
2897impl Trait<i64> for S<u64> {}
2898impl Trait<i32> for S<u32> {}
2899fn test() {
2900 let a: (S<u64>, _) = S::make();
2901 let b: (_, i32) = S::make();
2902}
2903"#),
2904 @r###"
2905 [131; 203) '{ ...e(); }': ()
2906 [141; 142) 'a': (S<u64>, i64)
2907 [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T)
2908 [158; 167) 'S::make()': (S<u64>, i64)
2909 [177; 178) 'b': (S<u32>, i32)
2910 [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T)
2911 [191; 200) 'S::make()': (S<u32>, i32)
2912 "###
2913 );
2914}
2915
2916#[test]
2917fn infer_trait_assoc_method_generics_5() {
2918 assert_snapshot!(
2919 infer(r#"
2920trait Trait<T> {
2921 fn make<U>() -> (Self, T, U);
2922}
2923struct S<T>;
2924impl Trait<i64> for S<u64> {}
2925fn test() {
2926 let a = <S as Trait<i64>>::make::<u8>();
2927 let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>();
2928}
2929"#),
2930 @r###"
2931 [107; 211) '{ ...>(); }': ()
2932 [117; 118) 'a': (S<u64>, i64, u8)
2933 [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2934 [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8)
2935 [162; 163) 'b': (S<u64>, i64, u8)
2936 [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
2937 [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8)
2938 "###
2939 );
2940}
2941
2942#[test]
2796fn infer_from_bound_1() { 2943fn infer_from_bound_1() {
2797 assert_snapshot!( 2944 assert_snapshot!(
2798 infer(r#" 2945 infer(r#"
@@ -3256,7 +3403,7 @@ fn test() { S.foo()<|>; }
3256 3403
3257#[test] 3404#[test]
3258fn infer_macro_with_dollar_crate_is_correct_in_expr() { 3405fn infer_macro_with_dollar_crate_is_correct_in_expr() {
3259 covers!(macro_dollar_crate_other); 3406 // covers!(macro_dollar_crate_other);
3260 let (mut db, pos) = MockDatabase::with_position( 3407 let (mut db, pos) = MockDatabase::with_position(
3261 r#" 3408 r#"
3262//- /main.rs 3409//- /main.rs
@@ -3303,6 +3450,22 @@ fn test() { S.foo()<|>; }
3303 assert_eq!(t, "u128"); 3450 assert_eq!(t, "u128");
3304} 3451}
3305 3452
3453#[ignore]
3454#[test]
3455fn method_resolution_by_value_before_autoref() {
3456 let t = type_at(
3457 r#"
3458//- /main.rs
3459trait Clone { fn clone(&self) -> Self; }
3460struct S;
3461impl Clone for S {}
3462impl Clone for &S {}
3463fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; }
3464"#,
3465 );
3466 assert_eq!(t, "(S, S, &S)");
3467}
3468
3306#[test] 3469#[test]
3307fn method_resolution_trait_before_autoderef() { 3470fn method_resolution_trait_before_autoderef() {
3308 let t = type_at( 3471 let t = type_at(