diff options
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests.rs | 130 |
2 files changed, 184 insertions, 18 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d85a86c0a..a030cab47 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -310,7 +310,7 @@ impl DefCollector<'_> { | |||
310 | if export { | 310 | if export { |
311 | self.update( | 311 | self.update( |
312 | self.def_map.root, | 312 | self.def_map.root, |
313 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 313 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
314 | Visibility::Public, | 314 | Visibility::Public, |
315 | ImportType::Named, | 315 | ImportType::Named, |
316 | ); | 316 | ); |
@@ -336,7 +336,7 @@ impl DefCollector<'_> { | |||
336 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { | 336 | fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) { |
337 | self.update( | 337 | self.update( |
338 | self.def_map.root, | 338 | self.def_map.root, |
339 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 339 | &[(Some(name), PerNs::macros(macro_, Visibility::Public))], |
340 | Visibility::Public, | 340 | Visibility::Public, |
341 | ImportType::Named, | 341 | ImportType::Named, |
342 | ); | 342 | ); |
@@ -534,7 +534,7 @@ impl DefCollector<'_> { | |||
534 | let name = variant_data.name.clone(); | 534 | let name = variant_data.name.clone(); |
535 | let variant = EnumVariantId { parent: e, local_id }; | 535 | let variant = EnumVariantId { parent: e, local_id }; |
536 | let res = PerNs::both(variant.into(), variant.into(), vis); | 536 | let res = PerNs::both(variant.into(), variant.into(), vis); |
537 | (name, res) | 537 | (Some(name), res) |
538 | }) | 538 | }) |
539 | .collect::<Vec<_>>(); | 539 | .collect::<Vec<_>>(); |
540 | self.update(module_id, &resolutions, vis, ImportType::Glob); | 540 | self.update(module_id, &resolutions, vis, ImportType::Glob); |
@@ -550,15 +550,15 @@ impl DefCollector<'_> { | |||
550 | match import.path.segments.last() { | 550 | match import.path.segments.last() { |
551 | Some(last_segment) => { | 551 | Some(last_segment) => { |
552 | let name = match &import.alias { | 552 | let name = match &import.alias { |
553 | Some(ImportAlias::Alias(name)) => name.clone(), | 553 | Some(ImportAlias::Alias(name)) => Some(name.clone()), |
554 | Some(ImportAlias::Underscore) => last_segment.clone(), // FIXME rust-analyzer#2736 | 554 | Some(ImportAlias::Underscore) => None, |
555 | None => last_segment.clone(), | 555 | None => Some(last_segment.clone()), |
556 | }; | 556 | }; |
557 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); | 557 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |
558 | 558 | ||
559 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 | 559 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 |
560 | if import.is_extern_crate && module_id == self.def_map.root { | 560 | if import.is_extern_crate && module_id == self.def_map.root { |
561 | if let Some(def) = def.take_types() { | 561 | if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) { |
562 | self.def_map.extern_prelude.insert(name.clone(), def); | 562 | self.def_map.extern_prelude.insert(name.clone(), def); |
563 | } | 563 | } |
564 | } | 564 | } |
@@ -573,7 +573,7 @@ impl DefCollector<'_> { | |||
573 | fn update( | 573 | fn update( |
574 | &mut self, | 574 | &mut self, |
575 | module_id: LocalModuleId, | 575 | module_id: LocalModuleId, |
576 | resolutions: &[(Name, PerNs)], | 576 | resolutions: &[(Option<Name>, PerNs)], |
577 | vis: Visibility, | 577 | vis: Visibility, |
578 | import_type: ImportType, | 578 | import_type: ImportType, |
579 | ) { | 579 | ) { |
@@ -584,7 +584,7 @@ impl DefCollector<'_> { | |||
584 | fn update_recursive( | 584 | fn update_recursive( |
585 | &mut self, | 585 | &mut self, |
586 | module_id: LocalModuleId, | 586 | module_id: LocalModuleId, |
587 | resolutions: &[(Name, PerNs)], | 587 | resolutions: &[(Option<Name>, PerNs)], |
588 | // All resolutions are imported with this visibility; the visibilies in | 588 | // All resolutions are imported with this visibility; the visibilies in |
589 | // the `PerNs` values are ignored and overwritten | 589 | // the `PerNs` values are ignored and overwritten |
590 | vis: Visibility, | 590 | vis: Visibility, |
@@ -595,15 +595,51 @@ impl DefCollector<'_> { | |||
595 | // prevent stack overflows (but this shouldn't be possible) | 595 | // prevent stack overflows (but this shouldn't be possible) |
596 | panic!("infinite recursion in glob imports!"); | 596 | panic!("infinite recursion in glob imports!"); |
597 | } | 597 | } |
598 | let scope = &mut self.def_map.modules[module_id].scope; | ||
599 | let mut changed = false; | 598 | let mut changed = false; |
599 | |||
600 | for (name, res) in resolutions { | 600 | for (name, res) in resolutions { |
601 | changed |= scope.push_res_with_import( | 601 | match name { |
602 | &mut self.from_glob_import, | 602 | Some(name) => { |
603 | (module_id, name.clone()), | 603 | let scope = &mut self.def_map.modules[module_id].scope; |
604 | res.with_visibility(vis), | 604 | changed |= scope.push_res_with_import( |
605 | import_type, | 605 | &mut self.from_glob_import, |
606 | ); | 606 | (module_id, name.clone()), |
607 | res.with_visibility(vis), | ||
608 | import_type, | ||
609 | ); | ||
610 | } | ||
611 | None => { | ||
612 | let tr = match res.take_types() { | ||
613 | Some(ModuleDefId::TraitId(tr)) => tr, | ||
614 | Some(other) => { | ||
615 | log::debug!("non-trait `_` import of {:?}", other); | ||
616 | continue; | ||
617 | } | ||
618 | None => continue, | ||
619 | }; | ||
620 | let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr); | ||
621 | let should_update = match old_vis { | ||
622 | None => true, | ||
623 | Some(old_vis) => { | ||
624 | let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| { | ||
625 | panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr); | ||
626 | }); | ||
627 | |||
628 | if max_vis == old_vis { | ||
629 | false | ||
630 | } else { | ||
631 | mark::hit!(upgrade_underscore_visibility); | ||
632 | true | ||
633 | } | ||
634 | } | ||
635 | }; | ||
636 | |||
637 | if should_update { | ||
638 | changed = true; | ||
639 | self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis); | ||
640 | } | ||
641 | } | ||
642 | } | ||
607 | } | 643 | } |
608 | 644 | ||
609 | if !changed { | 645 | if !changed { |
@@ -950,7 +986,7 @@ impl ModCollector<'_, '_> { | |||
950 | .unwrap_or(Visibility::Public); | 986 | .unwrap_or(Visibility::Public); |
951 | self.def_collector.update( | 987 | self.def_collector.update( |
952 | self.module_id, | 988 | self.module_id, |
953 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], | 989 | &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], |
954 | vis, | 990 | vis, |
955 | ImportType::Named, | 991 | ImportType::Named, |
956 | ) | 992 | ) |
@@ -1057,7 +1093,7 @@ impl ModCollector<'_, '_> { | |||
1057 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1093 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1058 | self.def_collector.update( | 1094 | self.def_collector.update( |
1059 | self.module_id, | 1095 | self.module_id, |
1060 | &[(name, PerNs::from_def(def, vis, false))], | 1096 | &[(Some(name), PerNs::from_def(def, vis, false))], |
1061 | vis, | 1097 | vis, |
1062 | ImportType::Named, | 1098 | ImportType::Named, |
1063 | ); | 1099 | ); |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 205d3528b..839b1de57 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -558,3 +558,133 @@ mod b { | |||
558 | "#]], | 558 | "#]], |
559 | ); | 559 | ); |
560 | } | 560 | } |
561 | |||
562 | #[test] | ||
563 | fn underscore_import() { | ||
564 | check( | ||
565 | r#" | ||
566 | //- /main.rs | ||
567 | use tr::Tr as _; | ||
568 | use tr::Tr2 as _; | ||
569 | |||
570 | mod tr { | ||
571 | pub trait Tr {} | ||
572 | pub trait Tr2 {} | ||
573 | } | ||
574 | "#, | ||
575 | expect![[r#" | ||
576 | crate | ||
577 | _: t | ||
578 | _: t | ||
579 | tr: t | ||
580 | |||
581 | crate::tr | ||
582 | Tr: t | ||
583 | Tr2: t | ||
584 | "#]], | ||
585 | ); | ||
586 | } | ||
587 | |||
588 | #[test] | ||
589 | fn underscore_reexport() { | ||
590 | check( | ||
591 | r#" | ||
592 | //- /main.rs | ||
593 | mod tr { | ||
594 | pub trait PubTr {} | ||
595 | pub trait PrivTr {} | ||
596 | } | ||
597 | mod reex { | ||
598 | use crate::tr::PrivTr as _; | ||
599 | pub use crate::tr::PubTr as _; | ||
600 | } | ||
601 | use crate::reex::*; | ||
602 | "#, | ||
603 | expect![[r#" | ||
604 | crate | ||
605 | _: t | ||
606 | reex: t | ||
607 | tr: t | ||
608 | |||
609 | crate::tr | ||
610 | PrivTr: t | ||
611 | PubTr: t | ||
612 | |||
613 | crate::reex | ||
614 | _: t | ||
615 | _: t | ||
616 | "#]], | ||
617 | ); | ||
618 | } | ||
619 | |||
620 | #[test] | ||
621 | fn underscore_pub_crate_reexport() { | ||
622 | mark::check!(upgrade_underscore_visibility); | ||
623 | check( | ||
624 | r#" | ||
625 | //- /main.rs crate:main deps:lib | ||
626 | use lib::*; | ||
627 | |||
628 | //- /lib.rs crate:lib | ||
629 | use tr::Tr as _; | ||
630 | pub use tr::Tr as _; | ||
631 | |||
632 | mod tr { | ||
633 | pub trait Tr {} | ||
634 | } | ||
635 | "#, | ||
636 | expect![[r#" | ||
637 | crate | ||
638 | _: t | ||
639 | "#]], | ||
640 | ); | ||
641 | } | ||
642 | |||
643 | #[test] | ||
644 | fn underscore_nontrait() { | ||
645 | check( | ||
646 | r#" | ||
647 | //- /main.rs | ||
648 | mod m { | ||
649 | pub struct Struct; | ||
650 | pub enum Enum {} | ||
651 | pub const CONST: () = (); | ||
652 | } | ||
653 | use crate::m::{Struct as _, Enum as _, CONST as _}; | ||
654 | "#, | ||
655 | expect![[r#" | ||
656 | crate | ||
657 | m: t | ||
658 | |||
659 | crate::m | ||
660 | CONST: v | ||
661 | Enum: t | ||
662 | Struct: t v | ||
663 | "#]], | ||
664 | ); | ||
665 | } | ||
666 | |||
667 | #[test] | ||
668 | fn underscore_name_conflict() { | ||
669 | check( | ||
670 | r#" | ||
671 | //- /main.rs | ||
672 | struct Tr; | ||
673 | |||
674 | use tr::Tr as _; | ||
675 | |||
676 | mod tr { | ||
677 | pub trait Tr {} | ||
678 | } | ||
679 | "#, | ||
680 | expect![[r#" | ||
681 | crate | ||
682 | _: t | ||
683 | Tr: t v | ||
684 | tr: t | ||
685 | |||
686 | crate::tr | ||
687 | Tr: t | ||
688 | "#]], | ||
689 | ); | ||
690 | } | ||