diff options
author | Jonas Schievink <[email protected]> | 2021-02-09 16:27:04 +0000 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-02-09 16:27:04 +0000 |
commit | e16d9dc5bd78dc0d2139367f25b403926f682df9 (patch) | |
tree | 83bccff0dce8543fd7035ce96ff57ba49220fe21 | |
parent | 34ad3d629a75c8bbc419c0159c213901ce8ad28d (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.rs | 215 |
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 | ||
11 | use crate::{ | 11 | use 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 | ||
529 | impl 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 | |||
572 | fn 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 | |||
590 | fn 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 | |||
629 | pub trait HasResolver: Copy { | 608 | pub 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; |