aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres.rs')
-rw-r--r--crates/ra_hir/src/nameres.rs77
1 files changed, 58 insertions, 19 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index bd920bfea..8067b8415 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -297,7 +297,14 @@ where
297 ); 297 );
298 (res, if res.is_none() { ReachedFixedPoint::No } else { ReachedFixedPoint::Yes }) 298 (res, if res.is_none() { ReachedFixedPoint::No } else { ReachedFixedPoint::Yes })
299 } else { 299 } else {
300 self.result.resolve_path_fp(self.db, ResolveMode::Import, original_module, &import.path) 300 let res = self.result.resolve_path_fp(
301 self.db,
302 ResolveMode::Import,
303 original_module,
304 &import.path,
305 );
306
307 (res.resolved_def, res.reached_fixedpoint)
301 }; 308 };
302 309
303 if reached_fixedpoint != ReachedFixedPoint::Yes { 310 if reached_fixedpoint != ReachedFixedPoint::Yes {
@@ -435,6 +442,27 @@ where
435 } 442 }
436} 443}
437 444
445#[derive(Debug, Clone)]
446struct ResolvePathResult {
447 resolved_def: PerNs<ModuleDef>,
448 segment_index: Option<usize>,
449 reached_fixedpoint: ReachedFixedPoint,
450}
451
452impl ResolvePathResult {
453 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
454 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
455 }
456
457 fn with(
458 resolved_def: PerNs<ModuleDef>,
459 reached_fixedpoint: ReachedFixedPoint,
460 segment_index: Option<usize>,
461 ) -> ResolvePathResult {
462 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index }
463 }
464}
465
438#[derive(Debug, Clone, Copy, PartialEq, Eq)] 466#[derive(Debug, Clone, Copy, PartialEq, Eq)]
439enum ResolveMode { 467enum ResolveMode {
440 Import, 468 Import,
@@ -468,8 +496,9 @@ impl ItemMap {
468 db: &impl PersistentHirDatabase, 496 db: &impl PersistentHirDatabase,
469 original_module: Module, 497 original_module: Module,
470 path: &Path, 498 path: &Path,
471 ) -> PerNs<ModuleDef> { 499 ) -> (PerNs<ModuleDef>, Option<usize>) {
472 self.resolve_path_fp(db, ResolveMode::Other, original_module, path).0 500 let res = self.resolve_path_fp(db, ResolveMode::Other, original_module, path);
501 (res.resolved_def, res.segment_index)
473 } 502 }
474 503
475 fn resolve_in_prelude( 504 fn resolve_in_prelude(
@@ -534,7 +563,7 @@ impl ItemMap {
534 mode: ResolveMode, 563 mode: ResolveMode,
535 original_module: Module, 564 original_module: Module,
536 path: &Path, 565 path: &Path,
537 ) -> (PerNs<ModuleDef>, ReachedFixedPoint) { 566 ) -> ResolvePathResult {
538 let mut segments = path.segments.iter().enumerate(); 567 let mut segments = path.segments.iter().enumerate();
539 let mut curr_per_ns: PerNs<ModuleDef> = match path.kind { 568 let mut curr_per_ns: PerNs<ModuleDef> = match path.kind {
540 PathKind::Crate => PerNs::types(original_module.crate_root(db).into()), 569 PathKind::Crate => PerNs::types(original_module.crate_root(db).into()),
@@ -549,7 +578,7 @@ impl ItemMap {
549 { 578 {
550 let segment = match segments.next() { 579 let segment = match segments.next() {
551 Some((_, segment)) => segment, 580 Some((_, segment)) => segment,
552 None => return (PerNs::none(), ReachedFixedPoint::Yes), 581 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
553 }; 582 };
554 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 583 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
555 self.resolve_name_in_crate_root_or_extern_prelude( 584 self.resolve_name_in_crate_root_or_extern_prelude(
@@ -561,7 +590,7 @@ impl ItemMap {
561 PathKind::Plain => { 590 PathKind::Plain => {
562 let segment = match segments.next() { 591 let segment = match segments.next() {
563 Some((_, segment)) => segment, 592 Some((_, segment)) => segment,
564 None => return (PerNs::none(), ReachedFixedPoint::Yes), 593 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
565 }; 594 };
566 log::debug!("resolving {:?} in module", segment); 595 log::debug!("resolving {:?} in module", segment);
567 self.resolve_name_in_module(db, original_module, &segment.name) 596 self.resolve_name_in_module(db, original_module, &segment.name)
@@ -571,20 +600,20 @@ impl ItemMap {
571 PerNs::types(p.into()) 600 PerNs::types(p.into())
572 } else { 601 } else {
573 log::debug!("super path in root module"); 602 log::debug!("super path in root module");
574 return (PerNs::none(), ReachedFixedPoint::Yes); 603 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
575 } 604 }
576 } 605 }
577 PathKind::Abs => { 606 PathKind::Abs => {
578 // 2018-style absolute path -- only extern prelude 607 // 2018-style absolute path -- only extern prelude
579 let segment = match segments.next() { 608 let segment = match segments.next() {
580 Some((_, segment)) => segment, 609 Some((_, segment)) => segment,
581 None => return (PerNs::none(), ReachedFixedPoint::Yes), 610 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
582 }; 611 };
583 if let Some(def) = self.extern_prelude.get(&segment.name) { 612 if let Some(def) = self.extern_prelude.get(&segment.name) {
584 log::debug!("absolute path {:?} resolved to crate {:?}", path, def); 613 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
585 PerNs::types(*def) 614 PerNs::types(*def)
586 } else { 615 } else {
587 return (PerNs::none(), ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude 616 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
588 } 617 }
589 } 618 }
590 }; 619 };
@@ -598,7 +627,7 @@ impl ItemMap {
598 // (don't break here because `curr_per_ns` might contain 627 // (don't break here because `curr_per_ns` might contain
599 // something in the value namespace, and it would be wrong 628 // something in the value namespace, and it would be wrong
600 // to return that) 629 // to return that)
601 return (PerNs::none(), ReachedFixedPoint::No); 630 return ResolvePathResult::empty(ReachedFixedPoint::No);
602 } 631 }
603 }; 632 };
604 // resolve segment in curr 633 // resolve segment in curr
@@ -612,15 +641,15 @@ impl ItemMap {
612 }; 641 };
613 log::debug!("resolving {:?} in other crate", path); 642 log::debug!("resolving {:?} in other crate", path);
614 let item_map = db.item_map(module.krate); 643 let item_map = db.item_map(module.krate);
615 let def = item_map.resolve_path(db, *module, &path); 644 let (def, s) = item_map.resolve_path(db, *module, &path);
616 return (def, ReachedFixedPoint::Yes); 645 return ResolvePathResult::with(def, ReachedFixedPoint::Yes, s);
617 } 646 }
618 647
619 match self[module.module_id].items.get(&segment.name) { 648 match self[module.module_id].items.get(&segment.name) {
620 Some(res) if !res.def.is_none() => res.def, 649 Some(res) if !res.def.is_none() => res.def,
621 _ => { 650 _ => {
622 log::debug!("path segment {:?} not found", segment.name); 651 log::debug!("path segment {:?} not found", segment.name);
623 return (PerNs::none(), ReachedFixedPoint::No); 652 return ResolvePathResult::empty(ReachedFixedPoint::No);
624 } 653 }
625 } 654 }
626 } 655 }
@@ -629,23 +658,33 @@ impl ItemMap {
629 tested_by!(item_map_enum_importing); 658 tested_by!(item_map_enum_importing);
630 match e.variant(db, &segment.name) { 659 match e.variant(db, &segment.name) {
631 Some(variant) => PerNs::both(variant.into(), variant.into()), 660 Some(variant) => PerNs::both(variant.into(), variant.into()),
632 None => PerNs::none(), 661 None => {
662 return ResolvePathResult::with(
663 PerNs::types((*e).into()),
664 ReachedFixedPoint::Yes,
665 Some(i),
666 );
667 }
633 } 668 }
634 } 669 }
635 _ => { 670 s => {
636 // could be an inherent method call in UFCS form 671 // could be an inherent method call in UFCS form
637 // (`Struct::method`), or some other kind of associated 672 // (`Struct::method`), or some other kind of associated item
638 // item... Which we currently don't handle (TODO)
639 log::debug!( 673 log::debug!(
640 "path segment {:?} resolved to non-module {:?}, but is not last", 674 "path segment {:?} resolved to non-module {:?}, but is not last",
641 segment.name, 675 segment.name,
642 curr, 676 curr,
643 ); 677 );
644 return (PerNs::none(), ReachedFixedPoint::Yes); 678
679 return ResolvePathResult::with(
680 PerNs::types((*s).into()),
681 ReachedFixedPoint::Yes,
682 Some(i),
683 );
645 } 684 }
646 }; 685 };
647 } 686 }
648 (curr_per_ns, ReachedFixedPoint::Yes) 687 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
649 } 688 }
650} 689}
651 690