aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-02-09 16:27:04 +0000
committerJonas Schievink <[email protected]>2021-02-09 16:27:04 +0000
commite16d9dc5bd78dc0d2139367f25b403926f682df9 (patch)
tree83bccff0dce8543fd7035ce96ff57ba49220fe21
parent34ad3d629a75c8bbc419c0159c213901ce8ad28d (diff)
Use `block_def_map` in `Resolver`
This required a few changes to not bail out immediately if a `ModuleScope` doesn't resolve a path. The `LocalItemsScope` hack is now removed.
-rw-r--r--crates/hir_def/src/resolver.rs215
1 files changed, 97 insertions, 118 deletions
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index f9ad50301..e293aa425 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -10,7 +10,6 @@ use rustc_hash::FxHashSet;
10 10
11use crate::{ 11use crate::{
12 body::scope::{ExprScopes, ScopeId}, 12 body::scope::{ExprScopes, ScopeId},
13 body::Body,
14 builtin_type::BuiltinType, 13 builtin_type::BuiltinType,
15 db::DefDatabase, 14 db::DefDatabase,
16 expr::{ExprId, PatId}, 15 expr::{ExprId, PatId},
@@ -58,8 +57,6 @@ enum Scope {
58 AdtScope(AdtId), 57 AdtScope(AdtId),
59 /// Local bindings 58 /// Local bindings
60 ExprScope(ExprScope), 59 ExprScope(ExprScope),
61 /// Temporary hack to support local items.
62 LocalItemsScope(Arc<Body>),
63} 60}
64 61
65#[derive(Debug, Clone, PartialEq, Eq, Hash)] 62#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -169,13 +166,7 @@ impl Resolver {
169 for scope in self.scopes.iter().rev() { 166 for scope in self.scopes.iter().rev() {
170 match scope { 167 match scope {
171 Scope::ExprScope(_) => continue, 168 Scope::ExprScope(_) => continue,
172 Scope::GenericParams { .. } 169 Scope::GenericParams { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue,
173 | Scope::ImplDefScope(_)
174 | Scope::LocalItemsScope(_)
175 if skip_to_mod =>
176 {
177 continue
178 }
179 170
180 Scope::GenericParams { params, def } => { 171 Scope::GenericParams { params, def } => {
181 if let Some(local_id) = params.find_type_by_name(first_name) { 172 if let Some(local_id) = params.find_type_by_name(first_name) {
@@ -199,41 +190,13 @@ impl Resolver {
199 } 190 }
200 } 191 }
201 Scope::ModuleScope(m) => { 192 Scope::ModuleScope(m) => {
202 let (module_def, idx) = m.crate_def_map.resolve_path( 193 if let Some(res) = m.resolve_path_in_type_ns(db, path) {
203 db, 194 return Some(res);
204 m.module_id,
205 &path,
206 BuiltinShadowMode::Other,
207 );
208 let res = to_type_ns(module_def)?;
209 return Some((res, idx));
210 }
211 Scope::LocalItemsScope(body) => {
212 let def = body.item_scope.get(first_name);
213 if let Some(res) = to_type_ns(def) {
214 return Some((res, None));
215 } 195 }
216 } 196 }
217 } 197 }
218 } 198 }
219 return None; 199 None
220 fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
221 let res = match per_ns.take_types()? {
222 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
223 ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
224
225 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
226 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
227
228 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
229
230 ModuleDefId::FunctionId(_)
231 | ModuleDefId::ConstId(_)
232 | ModuleDefId::StaticId(_)
233 | ModuleDefId::ModuleId(_) => return None,
234 };
235 Some(res)
236 }
237 } 200 }
238 201
239 pub fn resolve_path_in_type_ns_fully( 202 pub fn resolve_path_in_type_ns_fully(
@@ -280,7 +243,6 @@ impl Resolver {
280 | Scope::ExprScope(_) 243 | Scope::ExprScope(_)
281 | Scope::GenericParams { .. } 244 | Scope::GenericParams { .. }
282 | Scope::ImplDefScope(_) 245 | Scope::ImplDefScope(_)
283 | Scope::LocalItemsScope(_)
284 if skip_to_mod => 246 if skip_to_mod =>
285 { 247 {
286 continue 248 continue
@@ -335,63 +297,14 @@ impl Resolver {
335 } 297 }
336 298
337 Scope::ModuleScope(m) => { 299 Scope::ModuleScope(m) => {
338 let (module_def, idx) = m.crate_def_map.resolve_path( 300 if let Some(def) = m.resolve_path_in_value_ns(db, path) {
339 db, 301 return Some(def);
340 m.module_id,
341 &path,
342 BuiltinShadowMode::Other,
343 );
344 return match idx {
345 None => {
346 let value = to_value_ns(module_def)?;
347 Some(ResolveValueResult::ValueNs(value))
348 }
349 Some(idx) => {
350 let ty = match module_def.take_types()? {
351 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
352 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
353 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
354 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
355
356 ModuleDefId::ModuleId(_)
357 | ModuleDefId::FunctionId(_)
358 | ModuleDefId::EnumVariantId(_)
359 | ModuleDefId::ConstId(_)
360 | ModuleDefId::StaticId(_) => return None,
361 };
362 Some(ResolveValueResult::Partial(ty, idx))
363 }
364 };
365 }
366 Scope::LocalItemsScope(body) => {
367 // we don't bother looking in the builtin scope here because there are no builtin values
368 let def = to_value_ns(body.item_scope.get(first_name));
369
370 if let Some(res) = def {
371 return Some(ResolveValueResult::ValueNs(res));
372 } 302 }
373 } 303 }
374 } 304 }
375 } 305 }
376 return None; 306
377 307 None
378 fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
379 let res = match per_ns.take_values()? {
380 ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
381 ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
382 ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
383 ModuleDefId::ConstId(it) => ValueNs::ConstId(it),
384 ModuleDefId::StaticId(it) => ValueNs::StaticId(it),
385
386 ModuleDefId::AdtId(AdtId::EnumId(_))
387 | ModuleDefId::AdtId(AdtId::UnionId(_))
388 | ModuleDefId::TraitId(_)
389 | ModuleDefId::TypeAliasId(_)
390 | ModuleDefId::BuiltinType(_)
391 | ModuleDefId::ModuleId(_) => return None,
392 };
393 Some(res)
394 }
395 } 308 }
396 309
397 pub fn resolve_path_in_value_ns_fully( 310 pub fn resolve_path_in_value_ns_fully(
@@ -410,11 +323,6 @@ impl Resolver {
410 db: &dyn DefDatabase, 323 db: &dyn DefDatabase,
411 path: &ModPath, 324 path: &ModPath,
412 ) -> Option<MacroDefId> { 325 ) -> Option<MacroDefId> {
413 // Search item scope legacy macro first
414 if let Some(def) = self.resolve_local_macro_def(path) {
415 return Some(def);
416 }
417
418 let (item_map, module) = self.module_scope()?; 326 let (item_map, module) = self.module_scope()?;
419 item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() 327 item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros()
420 } 328 }
@@ -447,16 +355,6 @@ impl Resolver {
447 }) 355 })
448 } 356 }
449 357
450 fn resolve_local_macro_def(&self, path: &ModPath) -> Option<MacroDefId> {
451 let name = path.as_ident()?;
452 self.scopes.iter().rev().find_map(|scope| {
453 if let Scope::LocalItemsScope(body) = scope {
454 return body.item_scope.get_legacy_macro(name);
455 }
456 None
457 })
458 }
459
460 pub fn module(&self) -> Option<ModuleId> { 358 pub fn module(&self) -> Option<ModuleId> {
461 let (def_map, local_id) = self.module_scope()?; 359 let (def_map, local_id) = self.module_scope()?;
462 Some(def_map.module_id(local_id)) 360 Some(def_map.module_id(local_id))
@@ -538,9 +436,6 @@ impl Scope {
538 }); 436 });
539 } 437 }
540 } 438 }
541 Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| {
542 f(name.clone(), ScopeDef::PerNs(def));
543 }),
544 &Scope::GenericParams { ref params, def: parent } => { 439 &Scope::GenericParams { ref params, def: parent } => {
545 for (local_id, param) in params.types.iter() { 440 for (local_id, param) in params.types.iter() {
546 if let Some(ref name) = param.name { 441 if let Some(ref name) = param.name {
@@ -584,10 +479,19 @@ pub fn resolver_for_scope(
584 scope_id: Option<ScopeId>, 479 scope_id: Option<ScopeId>,
585) -> Resolver { 480) -> Resolver {
586 let mut r = owner.resolver(db); 481 let mut r = owner.resolver(db);
587 r = r.push_local_items_scope(db.body(owner));
588 let scopes = db.expr_scopes(owner); 482 let scopes = db.expr_scopes(owner);
589 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); 483 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
590 for scope in scope_chain.into_iter().rev() { 484 for scope in scope_chain.into_iter().rev() {
485 if let Some(block) = scopes.block(scope) {
486 if let Some(def_map) = db.block_def_map(block) {
487 let root = def_map.root();
488 r = r.push_module_scope(def_map, root);
489 // FIXME: This adds as many module scopes as there are blocks, but resolving in each
490 // already traverses all parents, so this is O(n²). I think we could only store the
491 // innermost module scope instead?
492 }
493 }
494
591 r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); 495 r = r.push_expr_scope(owner, Arc::clone(&scopes), scope);
592 } 496 }
593 r 497 r
@@ -612,10 +516,6 @@ impl Resolver {
612 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 516 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
613 } 517 }
614 518
615 fn push_local_items_scope(self, body: Arc<Body>) -> Resolver {
616 self.push_scope(Scope::LocalItemsScope(body))
617 }
618
619 fn push_expr_scope( 519 fn push_expr_scope(
620 self, 520 self,
621 owner: DefWithBodyId, 521 owner: DefWithBodyId,
@@ -626,6 +526,85 @@ impl Resolver {
626 } 526 }
627} 527}
628 528
529impl ModuleItemMap {
530 pub fn resolve_path_in_value_ns(
531 &self,
532 db: &dyn DefDatabase,
533 path: &ModPath,
534 ) -> Option<ResolveValueResult> {
535 let (module_def, idx) =
536 self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
537 return match idx {
538 None => {
539 let value = to_value_ns(module_def)?;
540 Some(ResolveValueResult::ValueNs(value))
541 }
542 Some(idx) => {
543 let ty = match module_def.take_types()? {
544 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
545 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
546 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
547 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
548
549 ModuleDefId::ModuleId(_)
550 | ModuleDefId::FunctionId(_)
551 | ModuleDefId::EnumVariantId(_)
552 | ModuleDefId::ConstId(_)
553 | ModuleDefId::StaticId(_) => return None,
554 };
555 Some(ResolveValueResult::Partial(ty, idx))
556 }
557 };
558 }
559
560 pub fn resolve_path_in_type_ns(
561 &self,
562 db: &dyn DefDatabase,
563 path: &ModPath,
564 ) -> Option<(TypeNs, Option<usize>)> {
565 let (module_def, idx) =
566 self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
567 let res = to_type_ns(module_def)?;
568 Some((res, idx))
569 }
570}
571
572fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
573 let res = match per_ns.take_values()? {
574 ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
575 ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
576 ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
577 ModuleDefId::ConstId(it) => ValueNs::ConstId(it),
578 ModuleDefId::StaticId(it) => ValueNs::StaticId(it),
579
580 ModuleDefId::AdtId(AdtId::EnumId(_))
581 | ModuleDefId::AdtId(AdtId::UnionId(_))
582 | ModuleDefId::TraitId(_)
583 | ModuleDefId::TypeAliasId(_)
584 | ModuleDefId::BuiltinType(_)
585 | ModuleDefId::ModuleId(_) => return None,
586 };
587 Some(res)
588}
589
590fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
591 let res = match per_ns.take_types()? {
592 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
593 ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
594
595 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
596 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
597
598 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
599
600 ModuleDefId::FunctionId(_)
601 | ModuleDefId::ConstId(_)
602 | ModuleDefId::StaticId(_)
603 | ModuleDefId::ModuleId(_) => return None,
604 };
605 Some(res)
606}
607
629pub trait HasResolver: Copy { 608pub trait HasResolver: Copy {
630 /// Builds a resolver for type references inside this def. 609 /// Builds a resolver for type references inside this def.
631 fn resolver(self, db: &dyn DefDatabase) -> Resolver; 610 fn resolver(self, db: &dyn DefDatabase) -> Resolver;