@@ -630,15 +630,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
630
630
self . finalize_resolutions_in ( module) ;
631
631
}
632
632
633
- # [ derive ( Default ) ]
634
- struct UniformPathsCanaryResult < ' a > {
633
+ struct UniformPathsCanaryResults < ' a > {
634
+ name : Name ,
635
635
module_scope : Option < & ' a NameBinding < ' a > > ,
636
636
block_scopes : Vec < & ' a NameBinding < ' a > > ,
637
637
}
638
+
638
639
// Collect all tripped `uniform_paths` canaries separately.
639
640
let mut uniform_paths_canaries: BTreeMap <
640
- ( Span , NodeId ) ,
641
- ( Name , PerNS < UniformPathsCanaryResult > ) ,
641
+ ( Span , NodeId , Namespace ) ,
642
+ UniformPathsCanaryResults ,
642
643
> = BTreeMap :: new ( ) ;
643
644
644
645
let mut errors = false ;
@@ -665,21 +666,25 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
665
666
import. module_path . len ( ) > 0 &&
666
667
import. module_path [ 0 ] . name == keywords:: SelfValue . name ( ) ;
667
668
668
- let ( prev_name, canary_results) =
669
- uniform_paths_canaries. entry ( ( import. span , import. id ) )
670
- . or_insert ( ( name, PerNS :: default ( ) ) ) ;
671
-
672
- // All the canaries with the same `id` should have the same `name`.
673
- assert_eq ! ( * prev_name, name) ;
674
-
675
669
self . per_ns ( |_, ns| {
676
670
if let Some ( result) = result[ ns] . get ( ) . ok ( ) {
671
+ let canary_results =
672
+ uniform_paths_canaries. entry ( ( import. span , import. id , ns) )
673
+ . or_insert ( UniformPathsCanaryResults {
674
+ name,
675
+ module_scope : None ,
676
+ block_scopes : vec ! [ ] ,
677
+ } ) ;
678
+
679
+ // All the canaries with the same `id` should have the same `name`.
680
+ assert_eq ! ( canary_results. name, name) ;
681
+
677
682
if has_explicit_self {
678
683
// There should only be one `self::x` (module-scoped) canary.
679
- assert ! ( canary_results[ ns ] . module_scope. is_none( ) ) ;
680
- canary_results[ ns ] . module_scope = Some ( result) ;
684
+ assert ! ( canary_results. module_scope. is_none( ) ) ;
685
+ canary_results. module_scope = Some ( result) ;
681
686
} else {
682
- canary_results[ ns ] . block_scopes . push ( result) ;
687
+ canary_results. block_scopes . push ( result) ;
683
688
}
684
689
}
685
690
} ) ;
@@ -720,77 +725,72 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
720
725
}
721
726
722
727
let uniform_paths_feature = self . session . features_untracked ( ) . uniform_paths ;
723
- for ( ( span, _) , ( name, results) ) in uniform_paths_canaries {
724
- self . per_ns ( |this, ns| {
725
- let external_crate = if ns == TypeNS && this. extern_prelude . contains ( & name) {
726
- let crate_id =
727
- this. crate_loader . process_path_extern ( name, span) ;
728
- Some ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } )
729
- } else {
730
- None
731
- } ;
732
- let result_filter = |result : & & NameBinding | {
733
- // Ignore canaries that resolve to an import of the same crate.
734
- // That is, we allow `use crate_name; use crate_name::foo;`.
735
- if let Some ( def_id) = external_crate {
736
- if let Some ( module) = result. module ( ) {
737
- if module. normal_ancestor_id == def_id {
738
- return false ;
739
- }
740
- }
741
- }
728
+ for ( ( span, _, ns) , results) in uniform_paths_canaries {
729
+ let name = results. name ;
730
+ let external_crate = if ns == TypeNS && self . extern_prelude . contains ( & name) {
731
+ let crate_id =
732
+ self . crate_loader . process_path_extern ( name, span) ;
733
+ Some ( Def :: Mod ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } ) )
734
+ } else {
735
+ None
736
+ } ;
742
737
743
- true
744
- } ;
745
- let module_scope = results[ ns] . module_scope . filter ( result_filter) ;
746
- let block_scopes = || {
747
- results[ ns] . block_scopes . iter ( ) . cloned ( ) . filter ( result_filter)
748
- } ;
738
+ // Currently imports can't resolve in non-module scopes,
739
+ // we only have canaries in them for future-proofing.
740
+ if external_crate. is_none ( ) && results. module_scope . is_none ( ) {
741
+ return ;
742
+ }
743
+
744
+ {
745
+ let mut all_results = external_crate. into_iter ( ) . chain (
746
+ results. module_scope . iter ( )
747
+ . chain ( & results. block_scopes )
748
+ . map ( |binding| binding. def ( ) )
749
+ ) ;
750
+ let first = all_results. next ( ) . unwrap ( ) ;
749
751
750
- // An ambiguity requires more than one possible resolution.
752
+ // An ambiguity requires more than one *distinct* possible resolution.
751
753
let possible_resultions =
752
- ( external_crate. is_some ( ) as usize ) +
753
- ( module_scope. is_some ( ) as usize ) +
754
- ( block_scopes ( ) . next ( ) . is_some ( ) as usize ) ;
754
+ 1 + all_results. filter ( |& def| def != first) . count ( ) ;
755
755
if possible_resultions <= 1 {
756
756
return ;
757
757
}
758
+ }
758
759
759
- errors = true ;
760
+ errors = true ;
760
761
761
- let msg = format ! ( "`{}` import is ambiguous" , name) ;
762
- let mut err = this. session . struct_span_err ( span, & msg) ;
763
- let mut suggestion_choices = String :: new ( ) ;
764
- if external_crate. is_some ( ) {
765
- write ! ( suggestion_choices, "`::{}`" , name) ;
766
- err. span_label ( span,
767
- format ! ( "can refer to external crate `::{}`" , name) ) ;
768
- }
769
- if let Some ( result) = module_scope {
770
- if !suggestion_choices. is_empty ( ) {
771
- suggestion_choices. push_str ( " or " ) ;
772
- }
773
- write ! ( suggestion_choices, "`self::{}`" , name) ;
774
- if uniform_paths_feature {
775
- err. span_label ( result. span ,
776
- format ! ( "can refer to `self::{}`" , name) ) ;
777
- } else {
778
- err. span_label ( result. span ,
779
- format ! ( "may refer to `self::{}` in the future" , name) ) ;
780
- }
781
- }
782
- for result in block_scopes ( ) {
783
- err. span_label ( result. span ,
784
- format ! ( "shadowed by block-scoped `{}`" , name) ) ;
762
+ let msg = format ! ( "`{}` import is ambiguous" , name) ;
763
+ let mut err = self . session . struct_span_err ( span, & msg) ;
764
+ let mut suggestion_choices = String :: new ( ) ;
765
+ if external_crate. is_some ( ) {
766
+ write ! ( suggestion_choices, "`::{}`" , name) ;
767
+ err. span_label ( span,
768
+ format ! ( "can refer to external crate `::{}`" , name) ) ;
769
+ }
770
+ if let Some ( result) = results. module_scope {
771
+ if !suggestion_choices. is_empty ( ) {
772
+ suggestion_choices. push_str ( " or " ) ;
785
773
}
786
- err . help ( & format ! ( "write {} explicitly instead ", suggestion_choices ) ) ;
774
+ write ! ( suggestion_choices , "`self::{}` ", name ) ;
787
775
if uniform_paths_feature {
788
- err. note ( "relative `use` paths enabled by `#![feature(uniform_paths)]`" ) ;
776
+ err. span_label ( result. span ,
777
+ format ! ( "can refer to `self::{}`" , name) ) ;
789
778
} else {
790
- err. note ( "in the future, `#![feature(uniform_paths)]` may become the default" ) ;
779
+ err. span_label ( result. span ,
780
+ format ! ( "may refer to `self::{}` in the future" , name) ) ;
791
781
}
792
- err. emit ( ) ;
793
- } ) ;
782
+ }
783
+ for result in results. block_scopes {
784
+ err. span_label ( result. span ,
785
+ format ! ( "shadowed by block-scoped `{}`" , name) ) ;
786
+ }
787
+ err. help ( & format ! ( "write {} explicitly instead" , suggestion_choices) ) ;
788
+ if uniform_paths_feature {
789
+ err. note ( "relative `use` paths enabled by `#![feature(uniform_paths)]`" ) ;
790
+ } else {
791
+ err. note ( "in the future, `#![feature(uniform_paths)]` may become the default" ) ;
792
+ }
793
+ err. emit ( ) ;
794
794
}
795
795
796
796
if !error_vec. is_empty ( ) {
0 commit comments