diff options
Diffstat (limited to 'crates/ra_hir/src/nameres.rs')
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 77 |
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)] | ||
446 | struct ResolvePathResult { | ||
447 | resolved_def: PerNs<ModuleDef>, | ||
448 | segment_index: Option<usize>, | ||
449 | reached_fixedpoint: ReachedFixedPoint, | ||
450 | } | ||
451 | |||
452 | impl 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)] |
439 | enum ResolveMode { | 467 | enum 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 | ||