aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-07-21 16:52:43 +0100
committerJonas Schievink <[email protected]>2020-07-21 16:55:17 +0100
commitc07eaf868dab86d061ae80c098798a767b910e91 (patch)
tree1793a7f85fd45a0774e019aaa9fe16410ab6eda9 /crates/ra_hir_def/src/nameres
parent65b89b5471879a80fb6003c9fa0f8f93e2eb38e6 (diff)
Support `Trait as _` imports
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs67
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs131
2 files changed, 180 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..8913111f1 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,46 @@ 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 max_vis != old_vis
629 }
630 };
631
632 if should_update {
633 changed = true;
634 self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
635 }
636 }
637 }
607 } 638 }
608 639
609 if !changed { 640 if !changed {
@@ -950,7 +981,7 @@ impl ModCollector<'_, '_> {
950 .unwrap_or(Visibility::Public); 981 .unwrap_or(Visibility::Public);
951 self.def_collector.update( 982 self.def_collector.update(
952 self.module_id, 983 self.module_id,
953 &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], 984 &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
954 vis, 985 vis,
955 ImportType::Named, 986 ImportType::Named,
956 ) 987 )
@@ -1057,7 +1088,7 @@ impl ModCollector<'_, '_> {
1057 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 1088 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
1058 self.def_collector.update( 1089 self.def_collector.update(
1059 self.module_id, 1090 self.module_id,
1060 &[(name, PerNs::from_def(def, vis, false))], 1091 &[(Some(name), PerNs::from_def(def, vis, false))],
1061 vis, 1092 vis,
1062 ImportType::Named, 1093 ImportType::Named,
1063 ); 1094 );
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 205d3528b..502b1fb69 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -558,3 +558,134 @@ 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 check(
623 r#"
624//- /main.rs crate:main deps:lib
625use lib::*;
626
627//- /lib.rs crate:lib
628use tr::Tr as _;
629pub use tr::Tr as _;
630
631mod tr {
632 pub trait Tr {
633 fn method(&self) {}
634 }
635}
636 "#,
637 expect![[r#"
638 crate
639 _: t
640 "#]],
641 );
642}
643
644#[test]
645fn underscore_nontrait() {
646 check(
647 r#"
648//- /main.rs
649mod m {
650 pub struct Struct;
651 pub enum Enum {}
652 pub const CONST: () = ();
653}
654use crate::m::{Struct as _, Enum as _, CONST as _};
655 "#,
656 expect![[r#"
657 crate
658 m: t
659
660 crate::m
661 CONST: v
662 Enum: t
663 Struct: t v
664 "#]],
665 );
666}
667
668#[test]
669fn underscore_name_conflict() {
670 check(
671 r#"
672//- /main.rs
673struct Tr;
674
675use tr::Tr as _;
676
677mod tr {
678 pub trait Tr {}
679}
680 "#,
681 expect![[r#"
682 crate
683 _: t
684 Tr: t v
685 tr: t
686
687 crate::tr
688 Tr: t
689 "#]],
690 );
691}