@@ -630,15 +630,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
630630 self . finalize_resolutions_in ( module) ;
631631 }
632632
633- # [ derive ( Default ) ]
634- struct UniformPathsCanaryResult < ' a > {
633+ struct UniformPathsCanaryResults < ' a > {
634+ name : Name ,
635635 module_scope : Option < & ' a NameBinding < ' a > > ,
636636 block_scopes : Vec < & ' a NameBinding < ' a > > ,
637637 }
638+
638639 // Collect all tripped `uniform_paths` canaries separately.
639640 let mut uniform_paths_canaries: BTreeMap <
640- ( Span , NodeId ) ,
641- ( Name , PerNS < UniformPathsCanaryResult > ) ,
641+ ( Span , NodeId , Namespace ) ,
642+ UniformPathsCanaryResults ,
642643 > = BTreeMap :: new ( ) ;
643644
644645 let mut errors = false ;
@@ -665,21 +666,25 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
665666 import. module_path . len ( ) > 0 &&
666667 import. module_path [ 0 ] . name == keywords:: SelfValue . name ( ) ;
667668
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-
675669 self . per_ns ( |_, ns| {
676670 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+
677682 if has_explicit_self {
678683 // 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) ;
681686 } else {
682- canary_results[ ns ] . block_scopes . push ( result) ;
687+ canary_results. block_scopes . push ( result) ;
683688 }
684689 }
685690 } ) ;
@@ -720,77 +725,72 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
720725 }
721726
722727 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+ } ;
742737
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 ( ) ;
749751
750- // An ambiguity requires more than one possible resolution.
752+ // An ambiguity requires more than one *distinct* possible resolution.
751753 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 ( ) ;
755755 if possible_resultions <= 1 {
756756 return ;
757757 }
758+ }
758759
759- errors = true ;
760+ errors = true ;
760761
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 " ) ;
785773 }
786- err . help ( & format ! ( "write {} explicitly instead ", suggestion_choices ) ) ;
774+ write ! ( suggestion_choices , "`self::{}` ", name ) ;
787775 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) ) ;
789778 } 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) ) ;
791781 }
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 ( ) ;
794794 }
795795
796796 if !error_vec. is_empty ( ) {
0 commit comments