aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs72
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs130
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]
563fn underscore_import() {
564 check(
565 r#"
566//- /main.rs
567use tr::Tr as _;
568use tr::Tr2 as _;
569
570mod 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]
589fn underscore_reexport() {
590 check(
591 r#"
592//- /main.rs
593mod tr {
594 pub trait PubTr {}
595 pub trait PrivTr {}
596}
597mod reex {
598 use crate::tr::PrivTr as _;
599 pub use crate::tr::PubTr as _;
600}
601use 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]
621fn underscore_pub_crate_reexport() {
622 mark::check!(upgrade_underscore_visibility);
623 check(
624 r#"
625//- /main.rs crate:main deps:lib
626use lib::*;
627
628//- /lib.rs crate:lib
629use tr::Tr as _;
630pub use tr::Tr as _;
631
632mod tr {
633 pub trait Tr {}
634}
635 "#,
636 expect![[r#"
637 crate
638 _: t
639 "#]],
640 );
641}
642
643#[test]
644fn underscore_nontrait() {
645 check(
646 r#"
647//- /main.rs
648mod m {
649 pub struct Struct;
650 pub enum Enum {}
651 pub const CONST: () = ();
652}
653use 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]
668fn underscore_name_conflict() {
669 check(
670 r#"
671//- /main.rs
672struct Tr;
673
674use tr::Tr as _;
675
676mod 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}