aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-03-16 14:17:50 +0000
committerAleksey Kladov <[email protected]>2019-03-17 09:53:22 +0000
commit967a4b64af2f09e11108d28f11565fa0f3e583a5 (patch)
tree985072c007ce020de3c5205f0f976d872e44c41a /crates/ra_hir
parentd4449945a069d26035afe9d8627414f6dfc8bf0a (diff)
Reorganize name resolution
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model_api.rs3
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs3
-rw-r--r--crates/ra_hir/src/db.rs2
-rw-r--r--crates/ra_hir/src/nameres.rs462
-rw-r--r--crates/ra_hir/src/nameres/collector.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/collector.rs)4
-rw-r--r--crates/ra_hir/src/nameres/crate_def_map.rs368
-rw-r--r--crates/ra_hir/src/nameres/lower.rs40
-rw-r--r--crates/ra_hir/src/nameres/per_ns.rs78
-rw-r--r--crates/ra_hir/src/nameres/raw.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/raw.rs)41
-rw-r--r--crates/ra_hir/src/nameres/tests.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests.rs)0
-rw-r--r--crates/ra_hir/src/nameres/tests/globs.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs)0
-rw-r--r--crates/ra_hir/src/nameres/tests/incremental.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs)0
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs)0
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs2
14 files changed, 481 insertions, 522 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index c918ec9f6..c3124480b 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -8,8 +8,7 @@ use crate::{
8 Name, ScopesWithSourceMap, Ty, HirFileId, 8 Name, ScopesWithSourceMap, Ty, HirFileId,
9 HirDatabase, PersistentHirDatabase, 9 HirDatabase, PersistentHirDatabase,
10 type_ref::TypeRef, 10 type_ref::TypeRef,
11 nameres::{ModuleScope, Namespace, lower::ImportId}, 11 nameres::{ModuleScope, Namespace, ImportId, ModuleId},
12 nameres::crate_def_map::ModuleId,
13 expr::{Body, BodySourceMap}, 12 expr::{Body, BodySourceMap},
14 ty::InferenceResult, 13 ty::InferenceResult,
15 adt::{EnumVariantId, StructFieldId, VariantDef}, 14 adt::{EnumVariantId, StructFieldId, VariantDef},
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index aa4e62518..9f4448475 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -3,8 +3,7 @@ use ra_syntax::{ast, SyntaxNode, TreeArc, AstNode};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Problem, Name, 5 Module, ModuleSource, Problem, Name,
6 nameres::crate_def_map::ModuleId, 6 nameres::{ModuleId, ImportId},
7 nameres::lower::ImportId,
8 HirDatabase, PersistentHirDatabase, 7 HirDatabase, PersistentHirDatabase,
9 HirFileId, SourceItemId, 8 HirFileId, SourceItemId,
10}; 9};
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index b8c0a68a6..d2cc19b0f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -10,7 +10,7 @@ use crate::{
10 Struct, Enum, StructField, 10 Struct, Enum, StructField,
11 Const, ConstSignature, Static, 11 Const, ConstSignature, Static,
12 macros::MacroExpansion, 12 macros::MacroExpansion,
13 nameres::{Namespace, lower::{ImportSourceMap}, crate_def_map::{RawItems, CrateDefMap}}, 13 nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap},
14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig}, 14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig},
15 adt::{StructData, EnumData}, 15 adt::{StructData, EnumData},
16 impl_block::{ModuleImplBlocks, ImplSourceMap}, 16 impl_block::{ModuleImplBlocks, ImplSourceMap},
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 2248842de..30e959c04 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -1,35 +1,128 @@
1//! Name resolution algorithm. The end result of the algorithm is an `ItemMap`: 1/// This module implements import-resolution/macro expansion algorithm.
2//! a map which maps each module to its scope: the set of items visible in the 2///
3//! module. That is, we only resolve imports here, name resolution of item 3/// The result of this module is `CrateDefMap`: a datastructure which contains:
4//! bodies will be done in a separate step. 4///
5//! 5/// * a tree of modules for the crate
6//! Like Rustc, we use an interactive per-crate algorithm: we start with scopes 6/// * for each module, a set of items visible in the module (directly declared
7//! containing only directly defined items, and then iteratively resolve 7/// or imported)
8//! imports. 8///
9//! 9/// Note that `CrateDefMap` contains fully macro expanded code.
10//! To make this work nicely in the IDE scenario, we place `InputModuleItems` 10///
11//! in between raw syntax and name resolution. `InputModuleItems` are computed 11/// Computing `CrateDefMap` can be partitioned into several logically
12//! using only the module's syntax, and it is all directly defined items plus 12/// independent "phases". The phases are mutually recursive though, there's no
13//! imports. The plan is to make `InputModuleItems` independent of local 13/// stric ordering.
14//! modifications (that is, typing inside a function should not change IMIs), 14///
15//! so that the results of name resolution can be preserved unless the module 15/// ## Collecting RawItems
16//! structure itself is modified. 16///
17pub(crate) mod lower; 17/// This happens in the `raw` module, which parses a single source file into a
18pub(crate) mod crate_def_map; 18/// set of top-level items. Nested importa 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 unresovled imports and macros.
28///
29/// While we walk tree of modules, we also record macro_rules defenitions and
30/// expand calls to macro_rules defined macros.
31///
32/// ## Resolving Imports
33///
34/// TBD
35///
36/// ## Resolving Macros
37///
38/// While macro_rules from the same crate use a global mutable namespace, macros
39/// from other crates (including proc-macros) can be used with `foo::bar!`
40/// syntax.
41///
42/// TBD;
43
44mod per_ns;
45mod raw;
46mod collector;
47#[cfg(test)]
48mod tests;
49
50use std::sync::Arc;
19 51
20use rustc_hash::FxHashMap; 52use rustc_hash::FxHashMap;
21use ra_db::Edition; 53use ra_arena::{Arena, RawId, impl_arena_id};
54use ra_db::{FileId, Edition};
55use test_utils::tested_by;
22 56
23use crate::{ 57use crate::{
24 ModuleDef, Name, 58 ModuleDef, Name, Crate, Module, Problem,
25 nameres::lower::ImportId, 59 PersistentHirDatabase, Path, PathKind, HirFileId,
60 ids::{SourceItemId, SourceFileItemId},
26}; 61};
27 62
28pub(crate) use self::crate_def_map::{CrateDefMap, ModuleId}; 63pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap};
64
65pub use self::per_ns::{PerNs, Namespace};
66
67/// Contans all top-level defs from a macro-expanded crate
68#[derive(Debug, PartialEq, Eq)]
69pub struct CrateDefMap {
70 krate: Crate,
71 edition: Edition,
72 /// The prelude module for this crate. This either comes from an import
73 /// marked with the `prelude_import` attribute, or (in the normal case) from
74 /// a dependency (`std` or `core`).
75 prelude: Option<Module>,
76 extern_prelude: FxHashMap<Name, ModuleDef>,
77 root: ModuleId,
78 modules: Arena<ModuleId, ModuleData>,
79 public_macros: FxHashMap<Name, mbe::MacroRules>,
80 problems: CrateDefMapProblems,
81}
82
83impl std::ops::Index<ModuleId> for CrateDefMap {
84 type Output = ModuleData;
85 fn index(&self, id: ModuleId) -> &ModuleData {
86 &self.modules[id]
87 }
88}
89
90/// An ID of a module, **local** to a specific crate
91#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
92pub(crate) struct ModuleId(RawId);
93impl_arena_id!(ModuleId);
94
95#[derive(Default, Debug, PartialEq, Eq)]
96pub(crate) struct ModuleData {
97 pub(crate) parent: Option<ModuleId>,
98 pub(crate) children: FxHashMap<Name, ModuleId>,
99 pub(crate) scope: ModuleScope,
100 /// None for root
101 pub(crate) declaration: Option<SourceItemId>,
102 /// None for inline modules.
103 ///
104 /// Note that non-inline modules, by definition, live inside non-macro file.
105 pub(crate) definition: Option<FileId>,
106}
107
108#[derive(Default, Debug, PartialEq, Eq)]
109pub(crate) struct CrateDefMapProblems {
110 problems: Vec<(SourceItemId, Problem)>,
111}
112
113impl CrateDefMapProblems {
114 fn add(&mut self, source_item_id: SourceItemId, problem: Problem) {
115 self.problems.push((source_item_id, problem))
116 }
117
118 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a {
119 self.problems.iter().map(|(s, p)| (s, p))
120 }
121}
29 122
30#[derive(Debug, Default, PartialEq, Eq, Clone)] 123#[derive(Debug, Default, PartialEq, Eq, Clone)]
31pub struct ModuleScope { 124pub struct ModuleScope {
32 pub(crate) items: FxHashMap<Name, Resolution>, 125 items: FxHashMap<Name, Resolution>,
33} 126}
34 127
35impl ModuleScope { 128impl ModuleScope {
@@ -41,8 +134,6 @@ impl ModuleScope {
41 } 134 }
42} 135}
43 136
44/// `Resolution` is basically `DefId` atm, but it should account for stuff like
45/// multiple namespaces, ambiguity and errors.
46#[derive(Debug, Clone, PartialEq, Eq, Default)] 137#[derive(Debug, Clone, PartialEq, Eq, Default)]
47pub struct Resolution { 138pub struct Resolution {
48 /// None for unresolved 139 /// None for unresolved
@@ -51,114 +142,285 @@ pub struct Resolution {
51 pub import: Option<ImportId>, 142 pub import: Option<ImportId>,
52} 143}
53 144
54#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 145#[derive(Debug, Clone)]
55pub enum Namespace { 146struct ResolvePathResult {
56 Types, 147 resolved_def: PerNs<ModuleDef>,
57 Values, 148 segment_index: Option<usize>,
149 reached_fixedpoint: ReachedFixedPoint,
58} 150}
59 151
60#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 152impl ResolvePathResult {
61pub struct PerNs<T> { 153 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
62 pub types: Option<T>, 154 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
63 pub values: Option<T>, 155 }
64}
65 156
66impl<T> Default for PerNs<T> { 157 fn with(
67 fn default() -> Self { 158 resolved_def: PerNs<ModuleDef>,
68 PerNs { types: None, values: None } 159 reached_fixedpoint: ReachedFixedPoint,
160 segment_index: Option<usize>,
161 ) -> ResolvePathResult {
162 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index }
69 } 163 }
70} 164}
71 165
72impl<T> PerNs<T> { 166#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73 pub fn none() -> PerNs<T> { 167enum ResolveMode {
74 PerNs { types: None, values: None } 168 Import,
75 } 169 Other,
170}
76 171
77 pub fn values(t: T) -> PerNs<T> { 172#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78 PerNs { types: None, values: Some(t) } 173enum ReachedFixedPoint {
79 } 174 Yes,
175 No,
176}
80 177
81 pub fn types(t: T) -> PerNs<T> { 178impl CrateDefMap {
82 PerNs { types: Some(t), values: None } 179 pub(crate) fn crate_def_map_query(
180 db: &impl PersistentHirDatabase,
181 krate: Crate,
182 ) -> Arc<CrateDefMap> {
183 let def_map = {
184 let edition = krate.edition(db);
185 let mut modules: Arena<ModuleId, ModuleData> = Arena::default();
186 let root = modules.alloc(ModuleData::default());
187 CrateDefMap {
188 krate,
189 edition,
190 extern_prelude: FxHashMap::default(),
191 prelude: None,
192 root,
193 modules,
194 public_macros: FxHashMap::default(),
195 problems: CrateDefMapProblems::default(),
196 }
197 };
198 let def_map = collector::collect_defs(db, def_map);
199 Arc::new(def_map)
83 } 200 }
84 201
85 pub fn both(types: T, values: T) -> PerNs<T> { 202 pub(crate) fn root(&self) -> ModuleId {
86 PerNs { types: Some(types), values: Some(values) } 203 self.root
87 } 204 }
88 205
89 pub fn is_none(&self) -> bool { 206 pub(crate) fn problems(&self) -> &CrateDefMapProblems {
90 self.types.is_none() && self.values.is_none() 207 &self.problems
91 } 208 }
92 209
93 pub fn is_both(&self) -> bool { 210 pub(crate) fn mk_module(&self, module_id: ModuleId) -> Module {
94 self.types.is_some() && self.values.is_some() 211 Module { krate: self.krate, module_id }
95 } 212 }
96 213
97 pub fn take(self, namespace: Namespace) -> Option<T> { 214 pub(crate) fn prelude(&self) -> Option<Module> {
98 match namespace { 215 self.prelude
99 Namespace::Types => self.types,
100 Namespace::Values => self.values,
101 }
102 } 216 }
103 217
104 pub fn take_types(self) -> Option<T> { 218 pub(crate) fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDef> {
105 self.take(Namespace::Types) 219 &self.extern_prelude
106 } 220 }
107 221
108 pub fn take_values(self) -> Option<T> { 222 pub(crate) fn find_module_by_source(
109 self.take(Namespace::Values) 223 &self,
224 file_id: HirFileId,
225 decl_id: Option<SourceFileItemId>,
226 ) -> Option<ModuleId> {
227 let decl_id = decl_id.map(|it| it.with_file_id(file_id));
228 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
229 if decl_id.is_some() {
230 module_data.declaration == decl_id
231 } else {
232 module_data.definition.map(|it| it.into()) == Some(file_id)
233 }
234 })?;
235 Some(module_id)
110 } 236 }
111 237
112 pub fn get(&self, namespace: Namespace) -> Option<&T> { 238 pub(crate) fn resolve_path(
113 self.as_ref().take(namespace) 239 &self,
240 db: &impl PersistentHirDatabase,
241 original_module: ModuleId,
242 path: &Path,
243 ) -> (PerNs<ModuleDef>, Option<usize>) {
244 let res = self.resolve_path_fp(db, ResolveMode::Other, original_module, path);
245 (res.resolved_def, res.segment_index)
114 } 246 }
115 247
116 pub fn as_ref(&self) -> PerNs<&T> { 248 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
117 PerNs { types: self.types.as_ref(), values: self.values.as_ref() } 249 // the result.
118 } 250 fn resolve_path_fp(
251 &self,
252 db: &impl PersistentHirDatabase,
253 mode: ResolveMode,
254 original_module: ModuleId,
255 path: &Path,
256 ) -> ResolvePathResult {
257 let mut segments = path.segments.iter().enumerate();
258 let mut curr_per_ns: PerNs<ModuleDef> = match path.kind {
259 PathKind::Crate => {
260 PerNs::types(Module { krate: self.krate, module_id: self.root }.into())
261 }
262 PathKind::Self_ => {
263 PerNs::types(Module { krate: self.krate, module_id: original_module }.into())
264 }
265 // plain import or absolute path in 2015: crate-relative with
266 // fallback to extern prelude (with the simplification in
267 // rust-lang/rust#57745)
268 // TODO there must be a nicer way to write this condition
269 PathKind::Plain | PathKind::Abs
270 if self.edition == Edition::Edition2015
271 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
272 {
273 let segment = match segments.next() {
274 Some((_, segment)) => segment,
275 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
276 };
277 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
278 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
279 }
280 PathKind::Plain => {
281 let segment = match segments.next() {
282 Some((_, segment)) => segment,
283 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
284 };
285 log::debug!("resolving {:?} in module", segment);
286 self.resolve_name_in_module(db, original_module, &segment.name)
287 }
288 PathKind::Super => {
289 if let Some(p) = self.modules[original_module].parent {
290 PerNs::types(Module { krate: self.krate, module_id: p }.into())
291 } else {
292 log::debug!("super path in root module");
293 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
294 }
295 }
296 PathKind::Abs => {
297 // 2018-style absolute path -- only extern prelude
298 let segment = match segments.next() {
299 Some((_, segment)) => segment,
300 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
301 };
302 if let Some(def) = self.extern_prelude.get(&segment.name) {
303 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
304 PerNs::types(*def)
305 } else {
306 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
307 }
308 }
309 };
119 310
120 pub fn or(self, other: PerNs<T>) -> PerNs<T> { 311 for (i, segment) in segments {
121 PerNs { types: self.types.or(other.types), values: self.values.or(other.values) } 312 let curr = match curr_per_ns.as_ref().take_types() {
122 } 313 Some(r) => r,
314 None => {
315 // we still have path segments left, but the path so far
316 // didn't resolve in the types namespace => no resolution
317 // (don't break here because `curr_per_ns` might contain
318 // something in the value namespace, and it would be wrong
319 // to return that)
320 return ResolvePathResult::empty(ReachedFixedPoint::No);
321 }
322 };
323 // resolve segment in curr
123 324
124 pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { 325 curr_per_ns = match curr {
125 PerNs { types: self.types.and_then(&f), values: self.values.and_then(&f) } 326 ModuleDef::Module(module) => {
126 } 327 if module.krate != self.krate {
328 let path = Path {
329 segments: path.segments[i..].iter().cloned().collect(),
330 kind: PathKind::Self_,
331 };
332 log::debug!("resolving {:?} in other crate", path);
333 let defp_map = db.crate_def_map(module.krate);
334 let (def, s) = defp_map.resolve_path(db, module.module_id, &path);
335 return ResolvePathResult::with(
336 def,
337 ReachedFixedPoint::Yes,
338 s.map(|s| s + i),
339 );
340 }
127 341
128 pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> { 342 match self[module.module_id].scope.items.get(&segment.name) {
129 PerNs { types: self.types.map(&f), values: self.values.map(&f) } 343 Some(res) if !res.def.is_none() => res.def,
344 _ => {
345 log::debug!("path segment {:?} not found", segment.name);
346 return ResolvePathResult::empty(ReachedFixedPoint::No);
347 }
348 }
349 }
350 ModuleDef::Enum(e) => {
351 // enum variant
352 tested_by!(can_import_enum_variant);
353 match e.variant(db, &segment.name) {
354 Some(variant) => PerNs::both(variant.into(), variant.into()),
355 None => {
356 return ResolvePathResult::with(
357 PerNs::types((*e).into()),
358 ReachedFixedPoint::Yes,
359 Some(i),
360 );
361 }
362 }
363 }
364 s => {
365 // could be an inherent method call in UFCS form
366 // (`Struct::method`), or some other kind of associated item
367 log::debug!(
368 "path segment {:?} resolved to non-module {:?}, but is not last",
369 segment.name,
370 curr,
371 );
372
373 return ResolvePathResult::with(
374 PerNs::types((*s).into()),
375 ReachedFixedPoint::Yes,
376 Some(i),
377 );
378 }
379 };
380 }
381 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
130 } 382 }
131}
132 383
133#[derive(Debug, Clone)] 384 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
134struct ResolvePathResult { 385 let from_crate_root =
135 resolved_def: PerNs<ModuleDef>, 386 self[self.root].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
136 segment_index: Option<usize>, 387 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
137 reached_fixedpoint: ReachedFixedPoint,
138}
139 388
140impl ResolvePathResult { 389 from_crate_root.or(from_extern_prelude)
141 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
142 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
143 } 390 }
144 391
145 fn with( 392 pub(crate) fn resolve_name_in_module(
146 resolved_def: PerNs<ModuleDef>, 393 &self,
147 reached_fixedpoint: ReachedFixedPoint, 394 db: &impl PersistentHirDatabase,
148 segment_index: Option<usize>, 395 module: ModuleId,
149 ) -> ResolvePathResult { 396 name: &Name,
150 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index } 397 ) -> PerNs<ModuleDef> {
398 // Resolve in:
399 // - current module / scope
400 // - extern prelude
401 // - std prelude
402 let from_scope = self[module].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
403 let from_extern_prelude =
404 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
405 let from_prelude = self.resolve_in_prelude(db, name);
406
407 from_scope.or(from_extern_prelude).or(from_prelude)
151 } 408 }
152}
153 409
154#[derive(Debug, Clone, Copy, PartialEq, Eq)] 410 fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
155enum ResolveMode { 411 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
156 Import, 412 }
157 Other,
158}
159 413
160#[derive(Debug, Clone, Copy, PartialEq, Eq)] 414 fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> {
161enum ReachedFixedPoint { 415 if let Some(prelude) = self.prelude {
162 Yes, 416 let resolution = if prelude.krate == self.krate {
163 No, 417 self[prelude.module_id].scope.items.get(name).cloned()
418 } else {
419 db.crate_def_map(prelude.krate)[prelude.module_id].scope.items.get(name).cloned()
420 };
421 resolution.map(|r| r.def).unwrap_or_else(PerNs::none)
422 } else {
423 PerNs::none()
424 }
425 }
164} 426}
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 0f500ce42..cbe850ba4 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -8,11 +8,11 @@ use crate::{
8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, 8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
9 PersistentHirDatabase, HirFileId, Name, Path, Problem, 9 PersistentHirDatabase, HirFileId, Name, Path, Problem,
10 KnownName, 10 KnownName,
11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode}, 11 nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw},
12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, 12 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId},
13}; 13};
14 14
15use super::{CrateDefMap, ModuleId, ModuleData, raw}; 15use super::{CrateDefMap, ModuleId, ModuleData};
16 16
17pub(super) fn collect_defs( 17pub(super) fn collect_defs(
18 db: &impl PersistentHirDatabase, 18 db: &impl PersistentHirDatabase,
diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs
deleted file mode 100644
index cc4955053..000000000
--- a/crates/ra_hir/src/nameres/crate_def_map.rs
+++ /dev/null
@@ -1,368 +0,0 @@
1/// This module implements new import-resolution/macro expansion algorithm.
2///
3/// The result of this module is `CrateDefMap`: a datastructure 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/// stric 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 importa 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 unresovled imports and macros.
28///
29/// While we walk tree of modules, we also record macro_rules defenitions and
30/// expand calls to macro_rules defined macros.
31///
32/// ## Resolving Imports
33///
34/// TBD
35///
36/// ## Resolving Macros
37///
38/// While macro_rules from the same crate use a global mutable namespace, macros
39/// from other crates (including proc-macros) can be used with `foo::bar!`
40/// syntax.
41///
42/// TBD;
43
44mod raw;
45mod collector;
46#[cfg(test)]
47mod tests;
48
49use rustc_hash::FxHashMap;
50use test_utils::tested_by;
51use ra_arena::{Arena, RawId, impl_arena_id};
52use ra_db::FileId;
53
54use std::sync::Arc;
55
56use crate::{
57 Name, Module, Path, PathKind, ModuleDef, Crate, Problem, HirFileId,
58 PersistentHirDatabase,
59 nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint},
60 ids::{SourceItemId, SourceFileItemId},
61};
62
63pub(crate) use self::raw::RawItems;
64
65#[derive(Default, Debug, PartialEq, Eq)]
66pub(crate) struct ModuleData {
67 pub(crate) parent: Option<ModuleId>,
68 pub(crate) children: FxHashMap<Name, ModuleId>,
69 pub(crate) scope: ModuleScope,
70 /// None for root
71 pub(crate) declaration: Option<SourceItemId>,
72 /// None for inline modules.
73 ///
74 /// Note that non-inline modules, by definition, live inside non-macro file.
75 pub(crate) definition: Option<FileId>,
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
79pub(crate) struct ModuleId(RawId);
80impl_arena_id!(ModuleId);
81
82/// Contans all top-level defs from a macro-expanded crate
83#[derive(Debug, PartialEq, Eq)]
84pub struct CrateDefMap {
85 krate: Crate,
86 edition: Edition,
87 /// The prelude module for this crate. This either comes from an import
88 /// marked with the `prelude_import` attribute, or (in the normal case) from
89 /// a dependency (`std` or `core`).
90 prelude: Option<Module>,
91 extern_prelude: FxHashMap<Name, ModuleDef>,
92 root: ModuleId,
93 modules: Arena<ModuleId, ModuleData>,
94 public_macros: FxHashMap<Name, mbe::MacroRules>,
95 problems: CrateDefMapProblems,
96}
97
98#[derive(Default, Debug, PartialEq, Eq)]
99pub(crate) struct CrateDefMapProblems {
100 problems: Vec<(SourceItemId, Problem)>,
101}
102
103impl CrateDefMapProblems {
104 fn add(&mut self, source_item_id: SourceItemId, problem: Problem) {
105 self.problems.push((source_item_id, problem))
106 }
107
108 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a {
109 self.problems.iter().map(|(s, p)| (s, p))
110 }
111}
112
113impl std::ops::Index<ModuleId> for CrateDefMap {
114 type Output = ModuleData;
115 fn index(&self, id: ModuleId) -> &ModuleData {
116 &self.modules[id]
117 }
118}
119
120impl CrateDefMap {
121 pub(crate) fn crate_def_map_query(
122 db: &impl PersistentHirDatabase,
123 krate: Crate,
124 ) -> Arc<CrateDefMap> {
125 let def_map = {
126 let edition = krate.edition(db);
127 let mut modules: Arena<ModuleId, ModuleData> = Arena::default();
128 let root = modules.alloc(ModuleData::default());
129 CrateDefMap {
130 krate,
131 edition,
132 extern_prelude: FxHashMap::default(),
133 prelude: None,
134 root,
135 modules,
136 public_macros: FxHashMap::default(),
137 problems: CrateDefMapProblems::default(),
138 }
139 };
140 let def_map = collector::collect_defs(db, def_map);
141 Arc::new(def_map)
142 }
143
144 pub(crate) fn root(&self) -> ModuleId {
145 self.root
146 }
147
148 pub(crate) fn problems(&self) -> &CrateDefMapProblems {
149 &self.problems
150 }
151
152 pub(crate) fn mk_module(&self, module_id: ModuleId) -> Module {
153 Module { krate: self.krate, module_id }
154 }
155
156 pub(crate) fn prelude(&self) -> Option<Module> {
157 self.prelude
158 }
159
160 pub(crate) fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDef> {
161 &self.extern_prelude
162 }
163
164 pub(crate) fn find_module_by_source(
165 &self,
166 file_id: HirFileId,
167 decl_id: Option<SourceFileItemId>,
168 ) -> Option<ModuleId> {
169 let decl_id = decl_id.map(|it| it.with_file_id(file_id));
170 let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
171 if decl_id.is_some() {
172 module_data.declaration == decl_id
173 } else {
174 module_data.definition.map(|it| it.into()) == Some(file_id)
175 }
176 })?;
177 Some(module_id)
178 }
179
180 pub(crate) fn resolve_path(
181 &self,
182 db: &impl PersistentHirDatabase,
183 original_module: ModuleId,
184 path: &Path,
185 ) -> (PerNs<ModuleDef>, Option<usize>) {
186 let res = self.resolve_path_fp(db, ResolveMode::Other, original_module, path);
187 (res.resolved_def, res.segment_index)
188 }
189
190 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
191 // the result.
192 fn resolve_path_fp(
193 &self,
194 db: &impl PersistentHirDatabase,
195 mode: ResolveMode,
196 original_module: ModuleId,
197 path: &Path,
198 ) -> ResolvePathResult {
199 let mut segments = path.segments.iter().enumerate();
200 let mut curr_per_ns: PerNs<ModuleDef> = match path.kind {
201 PathKind::Crate => {
202 PerNs::types(Module { krate: self.krate, module_id: self.root }.into())
203 }
204 PathKind::Self_ => {
205 PerNs::types(Module { krate: self.krate, module_id: original_module }.into())
206 }
207 // plain import or absolute path in 2015: crate-relative with
208 // fallback to extern prelude (with the simplification in
209 // rust-lang/rust#57745)
210 // TODO there must be a nicer way to write this condition
211 PathKind::Plain | PathKind::Abs
212 if self.edition == Edition::Edition2015
213 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
214 {
215 let segment = match segments.next() {
216 Some((_, segment)) => segment,
217 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
218 };
219 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
220 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
221 }
222 PathKind::Plain => {
223 let segment = match segments.next() {
224 Some((_, segment)) => segment,
225 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
226 };
227 log::debug!("resolving {:?} in module", segment);
228 self.resolve_name_in_module(db, original_module, &segment.name)
229 }
230 PathKind::Super => {
231 if let Some(p) = self.modules[original_module].parent {
232 PerNs::types(Module { krate: self.krate, module_id: p }.into())
233 } else {
234 log::debug!("super path in root module");
235 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
236 }
237 }
238 PathKind::Abs => {
239 // 2018-style absolute path -- only extern prelude
240 let segment = match segments.next() {
241 Some((_, segment)) => segment,
242 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
243 };
244 if let Some(def) = self.extern_prelude.get(&segment.name) {
245 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
246 PerNs::types(*def)
247 } else {
248 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
249 }
250 }
251 };
252
253 for (i, segment) in segments {
254 let curr = match curr_per_ns.as_ref().take_types() {
255 Some(r) => r,
256 None => {
257 // we still have path segments left, but the path so far
258 // didn't resolve in the types namespace => no resolution
259 // (don't break here because `curr_per_ns` might contain
260 // something in the value namespace, and it would be wrong
261 // to return that)
262 return ResolvePathResult::empty(ReachedFixedPoint::No);
263 }
264 };
265 // resolve segment in curr
266
267 curr_per_ns = match curr {
268 ModuleDef::Module(module) => {
269 if module.krate != self.krate {
270 let path = Path {
271 segments: path.segments[i..].iter().cloned().collect(),
272 kind: PathKind::Self_,
273 };
274 log::debug!("resolving {:?} in other crate", path);
275 let defp_map = db.crate_def_map(module.krate);
276 let (def, s) = defp_map.resolve_path(db, module.module_id, &path);
277 return ResolvePathResult::with(
278 def,
279 ReachedFixedPoint::Yes,
280 s.map(|s| s + i),
281 );
282 }
283
284 match self[module.module_id].scope.items.get(&segment.name) {
285 Some(res) if !res.def.is_none() => res.def,
286 _ => {
287 log::debug!("path segment {:?} not found", segment.name);
288 return ResolvePathResult::empty(ReachedFixedPoint::No);
289 }
290 }
291 }
292 ModuleDef::Enum(e) => {
293 // enum variant
294 tested_by!(can_import_enum_variant);
295 match e.variant(db, &segment.name) {
296 Some(variant) => PerNs::both(variant.into(), variant.into()),
297 None => {
298 return ResolvePathResult::with(
299 PerNs::types((*e).into()),
300 ReachedFixedPoint::Yes,
301 Some(i),
302 );
303 }
304 }
305 }
306 s => {
307 // could be an inherent method call in UFCS form
308 // (`Struct::method`), or some other kind of associated item
309 log::debug!(
310 "path segment {:?} resolved to non-module {:?}, but is not last",
311 segment.name,
312 curr,
313 );
314
315 return ResolvePathResult::with(
316 PerNs::types((*s).into()),
317 ReachedFixedPoint::Yes,
318 Some(i),
319 );
320 }
321 };
322 }
323 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
324 }
325
326 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
327 let from_crate_root =
328 self[self.root].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
329 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
330
331 from_crate_root.or(from_extern_prelude)
332 }
333
334 pub(crate) fn resolve_name_in_module(
335 &self,
336 db: &impl PersistentHirDatabase,
337 module: ModuleId,
338 name: &Name,
339 ) -> PerNs<ModuleDef> {
340 // Resolve in:
341 // - current module / scope
342 // - extern prelude
343 // - std prelude
344 let from_scope = self[module].scope.items.get(name).map_or(PerNs::none(), |it| it.def);
345 let from_extern_prelude =
346 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
347 let from_prelude = self.resolve_in_prelude(db, name);
348
349 from_scope.or(from_extern_prelude).or(from_prelude)
350 }
351
352 fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
353 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
354 }
355
356 fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> {
357 if let Some(prelude) = self.prelude {
358 let resolution = if prelude.krate == self.krate {
359 self[prelude.module_id].scope.items.get(name).cloned()
360 } else {
361 db.crate_def_map(prelude.krate)[prelude.module_id].scope.items.get(name).cloned()
362 };
363 resolution.map(|r| r.def).unwrap_or_else(PerNs::none)
364 } else {
365 PerNs::none()
366 }
367 }
368}
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
deleted file mode 100644
index d4c7f2481..000000000
--- a/crates/ra_hir/src/nameres/lower.rs
+++ /dev/null
@@ -1,40 +0,0 @@
1use ra_syntax::{
2 AstNode, SourceFile, TreeArc, AstPtr,
3 ast,
4};
5use ra_arena::{RawId, impl_arena_id, map::ArenaMap};
6
7use crate::{Path, ModuleSource, Name};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub struct ImportId(RawId);
11impl_arena_id!(ImportId);
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct ImportData {
15 pub(super) path: Path,
16 pub(super) alias: Option<Name>,
17 pub(super) is_glob: bool,
18 pub(super) is_prelude: bool,
19 pub(super) is_extern_crate: bool,
20}
21
22#[derive(Debug, Default, PartialEq, Eq)]
23pub struct ImportSourceMap {
24 map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>,
25}
26
27impl ImportSourceMap {
28 pub(crate) fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) {
29 self.map.insert(import, AstPtr::new(segment))
30 }
31
32 pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> {
33 let file = match source {
34 ModuleSource::SourceFile(file) => &*file,
35 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
36 };
37
38 self.map[import].to_node(file).to_owned()
39 }
40}
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs
new file mode 100644
index 000000000..c40a3ff9d
--- /dev/null
+++ b/crates/ra_hir/src/nameres/per_ns.rs
@@ -0,0 +1,78 @@
1#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub enum Namespace {
3 Types,
4 Values,
5}
6
7#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8pub struct PerNs<T> {
9 pub types: Option<T>,
10 pub values: Option<T>,
11}
12
13impl<T> Default for PerNs<T> {
14 fn default() -> Self {
15 PerNs { types: None, values: None }
16 }
17}
18
19impl<T> PerNs<T> {
20 pub fn none() -> PerNs<T> {
21 PerNs { types: None, values: None }
22 }
23
24 pub fn values(t: T) -> PerNs<T> {
25 PerNs { types: None, values: Some(t) }
26 }
27
28 pub fn types(t: T) -> PerNs<T> {
29 PerNs { types: Some(t), values: None }
30 }
31
32 pub fn both(types: T, values: T) -> PerNs<T> {
33 PerNs { types: Some(types), values: Some(values) }
34 }
35
36 pub fn is_none(&self) -> bool {
37 self.types.is_none() && self.values.is_none()
38 }
39
40 pub fn is_both(&self) -> bool {
41 self.types.is_some() && self.values.is_some()
42 }
43
44 pub fn take(self, namespace: Namespace) -> Option<T> {
45 match namespace {
46 Namespace::Types => self.types,
47 Namespace::Values => self.values,
48 }
49 }
50
51 pub fn take_types(self) -> Option<T> {
52 self.take(Namespace::Types)
53 }
54
55 pub fn take_values(self) -> Option<T> {
56 self.take(Namespace::Values)
57 }
58
59 pub fn get(&self, namespace: Namespace) -> Option<&T> {
60 self.as_ref().take(namespace)
61 }
62
63 pub fn as_ref(&self) -> PerNs<&T> {
64 PerNs { types: self.types.as_ref(), values: self.values.as_ref() }
65 }
66
67 pub fn or(self, other: PerNs<T>) -> PerNs<T> {
68 PerNs { types: self.types.or(other.types), values: self.values.or(other.values) }
69 }
70
71 pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> {
72 PerNs { types: self.types.and_then(&f), values: self.values.and_then(&f) }
73 }
74
75 pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> {
76 PerNs { types: self.types.map(&f), values: self.values.map(&f) }
77 }
78}
diff --git a/crates/ra_hir/src/nameres/crate_def_map/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index dca86e394..3226bbf0d 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -5,16 +5,15 @@ use std::{
5 5
6use test_utils::tested_by; 6use test_utils::tested_by;
7use ra_db::FileId; 7use ra_db::FileId;
8use ra_arena::{Arena, impl_arena_id, RawId}; 8use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap};
9use ra_syntax::{ 9use ra_syntax::{
10 AstNode, SourceFile, 10 AstNode, SourceFile, AstPtr, TreeArc,
11 ast::{self, NameOwner, AttrsOwner}, 11 ast::{self, NameOwner, AttrsOwner},
12}; 12};
13 13
14use crate::{ 14use crate::{
15 PersistentHirDatabase, Name, AsName, Path, HirFileId, 15 PersistentHirDatabase, Name, AsName, Path, HirFileId, ModuleSource,
16 ids::{SourceFileItemId, SourceFileItems}, 16 ids::{SourceFileItemId, SourceFileItems},
17 nameres::lower::ImportSourceMap,
18}; 17};
19 18
20#[derive(Debug, Default, PartialEq, Eq)] 19#[derive(Debug, Default, PartialEq, Eq)]
@@ -27,6 +26,26 @@ pub struct RawItems {
27 items: Vec<RawItem>, 26 items: Vec<RawItem>,
28} 27}
29 28
29#[derive(Debug, Default, PartialEq, Eq)]
30pub struct ImportSourceMap {
31 map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>,
32}
33
34impl ImportSourceMap {
35 pub(crate) fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) {
36 self.map.insert(import, AstPtr::new(segment))
37 }
38
39 pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> {
40 let file = match source {
41 ModuleSource::SourceFile(file) => &*file,
42 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
43 };
44
45 self.map[import].to_node(file).to_owned()
46 }
47}
48
30impl RawItems { 49impl RawItems {
31 pub(crate) fn raw_items_query( 50 pub(crate) fn raw_items_query(
32 db: &impl PersistentHirDatabase, 51 db: &impl PersistentHirDatabase,
@@ -113,8 +132,18 @@ pub(crate) enum ModuleData {
113 Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> }, 132 Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> },
114} 133}
115 134
116pub(crate) use crate::nameres::lower::ImportId; 135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
117pub(super) use crate::nameres::lower::ImportData; 136pub struct ImportId(RawId);
137impl_arena_id!(ImportId);
138
139#[derive(Debug, Clone, PartialEq, Eq)]
140pub struct ImportData {
141 pub(crate) path: Path,
142 pub(crate) alias: Option<Name>,
143 pub(crate) is_glob: bool,
144 pub(crate) is_prelude: bool,
145 pub(crate) is_extern_crate: bool,
146}
118 147
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 148#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
120pub(crate) struct Def(RawId); 149pub(crate) struct Def(RawId);
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 36c1d74ce..36c1d74ce 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs b/crates/ra_hir/src/nameres/tests/globs.rs
index 6e50c7ff6..6e50c7ff6 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs
+++ b/crates/ra_hir/src/nameres/tests/globs.rs
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
index 698781923..698781923 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs
+++ b/crates/ra_hir/src/nameres/tests/incremental.rs
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
index 8781b026b..8781b026b 100644
--- a/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 7c77474b0..1adf9eef9 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -11,7 +11,7 @@ use crate::{
11 ids::TraitId, 11 ids::TraitId,
12 impl_block::{ImplId, ImplBlock, ImplItem}, 12 impl_block::{ImplId, ImplBlock, ImplItem},
13 ty::{AdtDef, Ty}, 13 ty::{AdtDef, Ty},
14 nameres::crate_def_map::ModuleId, 14 nameres::ModuleId,
15 15
16}; 16};
17 17