@@ -620,9 +620,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
620
620
}
621
621
622
622
#[ derive( Default ) ]
623
- struct UniformPathsCanaryResult {
624
- module_scope : Option < Span > ,
625
- block_scopes : Vec < Span > ,
623
+ struct UniformPathsCanaryResult < ' a > {
624
+ module_scope : Option < & ' a NameBinding < ' a > > ,
625
+ block_scopes : Vec < & ' a NameBinding < ' a > > ,
626
626
}
627
627
// Collect all tripped `uniform_paths` canaries separately.
628
628
let mut uniform_paths_canaries: BTreeMap <
@@ -661,20 +661,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
661
661
662
662
self . per_ns ( |_, ns| {
663
663
if let Some ( result) = result[ ns] . get ( ) . ok ( ) {
664
- if let NameBindingKind :: Import { directive, .. } = result. kind {
665
- // Skip canaries that resolve to the import itself.
666
- // These come from `use crate_name;`, which isn't really
667
- // ambiguous, as the import can't actually shadow itself.
668
- if directive. id == import. id {
669
- return ;
670
- }
671
- }
672
664
if has_explicit_self {
673
665
// There should only be one `self::x` (module-scoped) canary.
674
- assert_eq ! ( canary_results[ ns] . module_scope, None ) ;
675
- canary_results[ ns] . module_scope = Some ( result. span ) ;
666
+ assert ! ( canary_results[ ns] . module_scope. is_none ( ) ) ;
667
+ canary_results[ ns] . module_scope = Some ( result) ;
676
668
} else {
677
- canary_results[ ns] . block_scopes . push ( result. span ) ;
669
+ canary_results[ ns] . block_scopes . push ( result) ;
678
670
}
679
671
}
680
672
} ) ;
@@ -708,16 +700,36 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
708
700
let uniform_paths_feature = self . session . features_untracked ( ) . uniform_paths ;
709
701
for ( ( span, _) , ( name, results) ) in uniform_paths_canaries {
710
702
self . per_ns ( |this, ns| {
711
- let results = & results[ ns] ;
703
+ let external_crate = if ns == TypeNS && this. extern_prelude . contains ( & name) {
704
+ let crate_id =
705
+ this. crate_loader . process_path_extern ( name, span) ;
706
+ Some ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } )
707
+ } else {
708
+ None
709
+ } ;
710
+ let result_filter = |result : & & NameBinding | {
711
+ // Ignore canaries that resolve to an import of the same crate.
712
+ // That is, we allow `use crate_name; use crate_name::foo;`.
713
+ if let Some ( def_id) = external_crate {
714
+ if let Some ( module) = result. module ( ) {
715
+ if module. normal_ancestor_id == def_id {
716
+ return false ;
717
+ }
718
+ }
719
+ }
712
720
713
- let has_external_crate =
714
- ns == TypeNS && this. extern_prelude . contains ( & name) ;
721
+ true
722
+ } ;
723
+ let module_scope = results[ ns] . module_scope . filter ( result_filter) ;
724
+ let block_scopes = || {
725
+ results[ ns] . block_scopes . iter ( ) . cloned ( ) . filter ( result_filter)
726
+ } ;
715
727
716
728
// An ambiguity requires more than one possible resolution.
717
729
let possible_resultions =
718
- ( has_external_crate as usize ) +
719
- ( results . module_scope . is_some ( ) as usize ) +
720
- ( !results . block_scopes . is_empty ( ) as usize ) ;
730
+ ( external_crate . is_some ( ) as usize ) +
731
+ ( module_scope. is_some ( ) as usize ) +
732
+ ( block_scopes ( ) . next ( ) . is_some ( ) as usize ) ;
721
733
if possible_resultions <= 1 {
722
734
return ;
723
735
}
@@ -727,26 +739,26 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
727
739
let msg = format ! ( "`{}` import is ambiguous" , name) ;
728
740
let mut err = this. session . struct_span_err ( span, & msg) ;
729
741
let mut suggestion_choices = String :: new ( ) ;
730
- if has_external_crate {
742
+ if external_crate . is_some ( ) {
731
743
write ! ( suggestion_choices, "`::{}`" , name) ;
732
744
err. span_label ( span,
733
745
format ! ( "can refer to external crate `::{}`" , name) ) ;
734
746
}
735
- if let Some ( span ) = results . module_scope {
747
+ if let Some ( result ) = module_scope {
736
748
if !suggestion_choices. is_empty ( ) {
737
749
suggestion_choices. push_str ( " or " ) ;
738
750
}
739
751
write ! ( suggestion_choices, "`self::{}`" , name) ;
740
752
if uniform_paths_feature {
741
- err. span_label ( span,
753
+ err. span_label ( result . span ,
742
754
format ! ( "can refer to `self::{}`" , name) ) ;
743
755
} else {
744
- err. span_label ( span,
756
+ err. span_label ( result . span ,
745
757
format ! ( "may refer to `self::{}` in the future" , name) ) ;
746
758
}
747
759
}
748
- for & span in & results . block_scopes {
749
- err. span_label ( span,
760
+ for result in block_scopes ( ) {
761
+ err. span_label ( result . span ,
750
762
format ! ( "shadowed by block-scoped `{}`" , name) ) ;
751
763
}
752
764
err. help ( & format ! ( "write {} explicitly instead" , suggestion_choices) ) ;
0 commit comments