diff options
author | Jonas Schievink <[email protected]> | 2020-07-21 16:52:43 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2020-07-21 16:55:17 +0100 |
commit | c07eaf868dab86d061ae80c098798a767b910e91 (patch) | |
tree | 1793a7f85fd45a0774e019aaa9fe16410ab6eda9 /crates/ra_hir_def/src/nameres | |
parent | 65b89b5471879a80fb6003c9fa0f8f93e2eb38e6 (diff) |
Support `Trait as _` imports
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 67 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests.rs | 131 |
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] | ||
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 | check( | ||
623 | r#" | ||
624 | //- /main.rs crate:main deps:lib | ||
625 | use lib::*; | ||
626 | |||
627 | //- /lib.rs crate:lib | ||
628 | use tr::Tr as _; | ||
629 | pub use tr::Tr as _; | ||
630 | |||
631 | mod 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] | ||
645 | fn underscore_nontrait() { | ||
646 | check( | ||
647 | r#" | ||
648 | //- /main.rs | ||
649 | mod m { | ||
650 | pub struct Struct; | ||
651 | pub enum Enum {} | ||
652 | pub const CONST: () = (); | ||
653 | } | ||
654 | use 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] | ||
669 | fn underscore_name_conflict() { | ||
670 | check( | ||
671 | r#" | ||
672 | //- /main.rs | ||
673 | struct Tr; | ||
674 | |||
675 | use tr::Tr as _; | ||
676 | |||
677 | mod 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 | } | ||